From 9e3371021541dbb7d8428b419c2e77156b166f1a Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:58:30 +0200 Subject: Imported nxagent-3.1.0-2.tar.gz Summary: Imported nxagent-3.1.0-2.tar.gz Keywords: Imported nxagent-3.1.0-2.tar.gz into Git repository --- nx-X11/programs/Xserver/hw/nxagent/Agent.h | 130 + nx-X11/programs/Xserver/hw/nxagent/Args.c | 2357 ++++++++ nx-X11/programs/Xserver/hw/nxagent/Args.h | 84 + nx-X11/programs/Xserver/hw/nxagent/Atoms.c | 785 +++ nx-X11/programs/Xserver/hw/nxagent/Atoms.h | 65 + nx-X11/programs/Xserver/hw/nxagent/Binder.c | 177 + nx-X11/programs/Xserver/hw/nxagent/Binder.h | 27 + nx-X11/programs/Xserver/hw/nxagent/CHANGELOG | 5815 ++++++++++++++++++++ nx-X11/programs/Xserver/hw/nxagent/COPYING | 339 ++ nx-X11/programs/Xserver/hw/nxagent/Client.c | 526 ++ nx-X11/programs/Xserver/hw/nxagent/Client.h | 119 + nx-X11/programs/Xserver/hw/nxagent/Clipboard.c | 1557 ++++++ nx-X11/programs/Xserver/hw/nxagent/Clipboard.h | 46 + nx-X11/programs/Xserver/hw/nxagent/Colormap.c | 577 ++ nx-X11/programs/Xserver/hw/nxagent/Colormap.h | 84 + nx-X11/programs/Xserver/hw/nxagent/Composite.c | 209 + nx-X11/programs/Xserver/hw/nxagent/Composite.h | 51 + nx-X11/programs/Xserver/hw/nxagent/Cursor.c | 601 ++ nx-X11/programs/Xserver/hw/nxagent/Cursor.h | 106 + nx-X11/programs/Xserver/hw/nxagent/Dialog.c | 563 ++ nx-X11/programs/Xserver/hw/nxagent/Dialog.h | 223 + nx-X11/programs/Xserver/hw/nxagent/Display.c | 2705 +++++++++ nx-X11/programs/Xserver/hw/nxagent/Display.h | 179 + nx-X11/programs/Xserver/hw/nxagent/Drawable.c | 3201 +++++++++++ nx-X11/programs/Xserver/hw/nxagent/Drawable.h | 221 + nx-X11/programs/Xserver/hw/nxagent/Error.c | 636 +++ nx-X11/programs/Xserver/hw/nxagent/Error.h | 37 + nx-X11/programs/Xserver/hw/nxagent/Events.c | 3822 +++++++++++++ nx-X11/programs/Xserver/hw/nxagent/Events.h | 223 + nx-X11/programs/Xserver/hw/nxagent/Extensions.c | 197 + nx-X11/programs/Xserver/hw/nxagent/Extensions.h | 35 + nx-X11/programs/Xserver/hw/nxagent/Font.c | 1690 ++++++ nx-X11/programs/Xserver/hw/nxagent/Font.h | 77 + nx-X11/programs/Xserver/hw/nxagent/GC.c | 1712 ++++++ nx-X11/programs/Xserver/hw/nxagent/GCOps.c | 1995 +++++++ nx-X11/programs/Xserver/hw/nxagent/GCOps.h | 105 + nx-X11/programs/Xserver/hw/nxagent/GCs.h | 111 + nx-X11/programs/Xserver/hw/nxagent/Handlers.c | 1272 +++++ nx-X11/programs/Xserver/hw/nxagent/Handlers.h | 121 + nx-X11/programs/Xserver/hw/nxagent/Holder.c | 226 + nx-X11/programs/Xserver/hw/nxagent/Holder.h | 27 + nx-X11/programs/Xserver/hw/nxagent/Icons.h | 29 + nx-X11/programs/Xserver/hw/nxagent/Image.c | 1816 ++++++ nx-X11/programs/Xserver/hw/nxagent/Image.h | 108 + nx-X11/programs/Xserver/hw/nxagent/Imakefile | 220 + nx-X11/programs/Xserver/hw/nxagent/Init.c | 491 ++ nx-X11/programs/Xserver/hw/nxagent/Init.h | 40 + nx-X11/programs/Xserver/hw/nxagent/Keyboard.c | 1359 +++++ nx-X11/programs/Xserver/hw/nxagent/Keyboard.h | 114 + nx-X11/programs/Xserver/hw/nxagent/Keystroke.c | 216 + nx-X11/programs/Xserver/hw/nxagent/Keystroke.h | 27 + nx-X11/programs/Xserver/hw/nxagent/LICENSE | 26 + nx-X11/programs/Xserver/hw/nxagent/Literals.h | 198 + nx-X11/programs/Xserver/hw/nxagent/Millis.c | 70 + nx-X11/programs/Xserver/hw/nxagent/Millis.h | 30 + nx-X11/programs/Xserver/hw/nxagent/NXcomposite.c | 359 ++ nx-X11/programs/Xserver/hw/nxagent/NXcomposite.h | 86 + .../programs/Xserver/hw/nxagent/NXcompositeext.h | 55 + .../programs/Xserver/hw/nxagent/NXcompositeint.h | 76 + .../programs/Xserver/hw/nxagent/NXcompositeproto.h | 148 + nx-X11/programs/Xserver/hw/nxagent/NXdamage.c | 5 + nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c | 4716 ++++++++++++++++ .../Xserver/hw/nxagent/NXdispatch.c.NX.original | 4716 ++++++++++++++++ .../Xserver/hw/nxagent/NXdispatch.c.XF86.original | 4110 ++++++++++++++ nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c | 2883 ++++++++++ .../Xserver/hw/nxagent/NXdixfonts.c.NX.original | 2883 ++++++++++ .../Xserver/hw/nxagent/NXdixfonts.c.XF86.original | 2223 ++++++++ nx-X11/programs/Xserver/hw/nxagent/NXevents.c | 4797 ++++++++++++++++ .../Xserver/hw/nxagent/NXevents.c.NX.original | 4797 ++++++++++++++++ .../Xserver/hw/nxagent/NXevents.c.XF86.original | 4637 ++++++++++++++++ nx-X11/programs/Xserver/hw/nxagent/NXextension.c | 528 ++ .../Xserver/hw/nxagent/NXextension.c.NX.original | 528 ++ .../Xserver/hw/nxagent/NXextension.c.XF86.original | 486 ++ nx-X11/programs/Xserver/hw/nxagent/NXglxext.c | 550 ++ .../Xserver/hw/nxagent/NXglxext.c.NX.original | 550 ++ .../Xserver/hw/nxagent/NXglxext.c.XF86.original | 489 ++ nx-X11/programs/Xserver/hw/nxagent/NXglyph.c | 511 ++ .../Xserver/hw/nxagent/NXglyph.c.NX.original | 511 ++ .../Xserver/hw/nxagent/NXglyph.c.XF86.original | 416 ++ nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c | 252 + .../Xserver/hw/nxagent/NXglyphcurs.c.NX.original | 252 + .../Xserver/hw/nxagent/NXglyphcurs.c.XF86.original | 197 + nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h | 161 + .../Xserver/hw/nxagent/NXglyphstr.h.NX.original | 161 + .../Xserver/hw/nxagent/NXglyphstr.h.XF86.original | 127 + nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c | 938 ++++ .../Xserver/hw/nxagent/NXmiexpose.c.NX.original | 938 ++++ .../Xserver/hw/nxagent/NXmiexpose.c.XF86.original | 873 +++ nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c | 322 ++ .../Xserver/hw/nxagent/NXmiglyph.c.NX.original | 322 ++ .../Xserver/hw/nxagent/NXmiglyph.c.XF86.original | 239 + nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c | 204 + .../Xserver/hw/nxagent/NXmitrap.c.NX.original | 204 + .../Xserver/hw/nxagent/NXmitrap.c.XF86.original | 196 + nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c | 1205 ++++ .../Xserver/hw/nxagent/NXmiwindow.c.NX.original | 1205 ++++ .../Xserver/hw/nxagent/NXmiwindow.c.XF86.original | 1176 ++++ nx-X11/programs/Xserver/hw/nxagent/NXpicture.c | 1512 +++++ .../Xserver/hw/nxagent/NXpicture.c.NX.original | 1512 +++++ .../Xserver/hw/nxagent/NXpicture.c.XF86.original | 1305 +++++ nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h | 533 ++ .../Xserver/hw/nxagent/NXpicturestr.h.NX.original | 533 ++ .../hw/nxagent/NXpicturestr.h.XF86.original | 501 ++ nx-X11/programs/Xserver/hw/nxagent/NXproperty.c | 921 ++++ .../Xserver/hw/nxagent/NXproperty.c.NX.original | 921 ++++ .../Xserver/hw/nxagent/NXproperty.c.XF86.original | 736 +++ nx-X11/programs/Xserver/hw/nxagent/NXrandr.c | 1229 +++++ .../Xserver/hw/nxagent/NXrandr.c.NX.original | 1229 +++++ .../Xserver/hw/nxagent/NXrandr.c.XF86.original | 1197 ++++ nx-X11/programs/Xserver/hw/nxagent/NXrender.c | 3048 ++++++++++ .../Xserver/hw/nxagent/NXrender.c.NX.original | 3048 ++++++++++ .../Xserver/hw/nxagent/NXrender.c.XF86.original | 2584 +++++++++ nx-X11/programs/Xserver/hw/nxagent/NXresource.c | 1103 ++++ .../Xserver/hw/nxagent/NXresource.c.NX.original | 1103 ++++ .../Xserver/hw/nxagent/NXresource.c.XF86.original | 975 ++++ nx-X11/programs/Xserver/hw/nxagent/NXshm.c | 1425 +++++ .../Xserver/hw/nxagent/NXshm.c.NX.original | 1425 +++++ .../Xserver/hw/nxagent/NXshm.c.XF86.original | 1257 +++++ nx-X11/programs/Xserver/hw/nxagent/NXwindow.c | 4179 ++++++++++++++ .../Xserver/hw/nxagent/NXwindow.c.NX.original | 4179 ++++++++++++++ .../Xserver/hw/nxagent/NXwindow.c.XF86.original | 3947 +++++++++++++ nx-X11/programs/Xserver/hw/nxagent/NXxrandr.c | 755 +++ nx-X11/programs/Xserver/hw/nxagent/NXxrandr.h | 168 + nx-X11/programs/Xserver/hw/nxagent/NXxrandrint.h | 104 + nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c | 2277 ++++++++ .../Xserver/hw/nxagent/NXxvdisp.c.NX.original | 2277 ++++++++ .../Xserver/hw/nxagent/NXxvdisp.c.XF86.original | 2214 ++++++++ nx-X11/programs/Xserver/hw/nxagent/Options.c | 178 + nx-X11/programs/Xserver/hw/nxagent/Options.h | 397 ++ nx-X11/programs/Xserver/hw/nxagent/Pixels.c | 384 ++ nx-X11/programs/Xserver/hw/nxagent/Pixels.h | 162 + nx-X11/programs/Xserver/hw/nxagent/Pixmap.c | 1646 ++++++ nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h | 136 + nx-X11/programs/Xserver/hw/nxagent/Pointer.c | 157 + nx-X11/programs/Xserver/hw/nxagent/Pointer.h | 45 + nx-X11/programs/Xserver/hw/nxagent/Reconnect.c | 788 +++ nx-X11/programs/Xserver/hw/nxagent/Reconnect.h | 68 + nx-X11/programs/Xserver/hw/nxagent/Render.c | 2810 ++++++++++ nx-X11/programs/Xserver/hw/nxagent/Render.h | 108 + nx-X11/programs/Xserver/hw/nxagent/Rootless.c | 1112 ++++ nx-X11/programs/Xserver/hw/nxagent/Rootless.h | 93 + nx-X11/programs/Xserver/hw/nxagent/Screen.c | 3984 ++++++++++++++ nx-X11/programs/Xserver/hw/nxagent/Screen.h | 130 + nx-X11/programs/Xserver/hw/nxagent/Splash.c | 335 ++ nx-X11/programs/Xserver/hw/nxagent/Splash.h | 45 + nx-X11/programs/Xserver/hw/nxagent/Split.c | 1248 +++++ nx-X11/programs/Xserver/hw/nxagent/Split.h | 84 + nx-X11/programs/Xserver/hw/nxagent/TestExt.c | 83 + nx-X11/programs/Xserver/hw/nxagent/Trap.c | 99 + nx-X11/programs/Xserver/hw/nxagent/Trap.h | 100 + nx-X11/programs/Xserver/hw/nxagent/Utils.h | 39 + nx-X11/programs/Xserver/hw/nxagent/Visual.c | 159 + nx-X11/programs/Xserver/hw/nxagent/Visual.h | 73 + nx-X11/programs/Xserver/hw/nxagent/Window.c | 3614 ++++++++++++ nx-X11/programs/Xserver/hw/nxagent/Windows.h | 300 + nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c | 2073 +++++++ .../Xserver/hw/nxagent/X/NXdamage.c.NX.original | 2073 +++++++ .../Xserver/hw/nxagent/X/NXdamage.c.X.original | 1966 +++++++ nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c | 4670 ++++++++++++++++ .../Xserver/hw/nxagent/X/NXdispatch.c.NX.original | 4670 ++++++++++++++++ .../Xserver/hw/nxagent/X/NXdispatch.c.X.original | 4035 ++++++++++++++ nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c | 2797 ++++++++++ .../Xserver/hw/nxagent/X/NXdixfonts.c.NX.original | 2797 ++++++++++ .../Xserver/hw/nxagent/X/NXdixfonts.c.X.original | 2143 ++++++++ nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c | 4827 ++++++++++++++++ .../Xserver/hw/nxagent/X/NXevents.c.NX.original | 4827 ++++++++++++++++ .../Xserver/hw/nxagent/X/NXevents.c.X.original | 4670 ++++++++++++++++ nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c | 508 ++ .../Xserver/hw/nxagent/X/NXextension.c.NX.original | 508 ++ .../Xserver/hw/nxagent/X/NXextension.c.X.original | 474 ++ nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c | 575 ++ .../Xserver/hw/nxagent/X/NXglxext.c.NX.original | 575 ++ .../Xserver/hw/nxagent/X/NXglxext.c.X.original | 505 ++ nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c | 566 ++ .../Xserver/hw/nxagent/X/NXglyph.c.NX.original | 566 ++ .../Xserver/hw/nxagent/X/NXglyph.c.X.original | 478 ++ nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c | 241 + .../Xserver/hw/nxagent/X/NXglyphcurs.c.NX.original | 241 + .../Xserver/hw/nxagent/X/NXglyphcurs.c.X.original | 194 + nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h | 174 + .../Xserver/hw/nxagent/X/NXglyphstr.h.NX.original | 174 + .../Xserver/hw/nxagent/X/NXglyphstr.h.X.original | 148 + nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c | 979 ++++ .../Xserver/hw/nxagent/X/NXmiexpose.c.NX.original | 979 ++++ .../Xserver/hw/nxagent/X/NXmiexpose.c.X.original | 905 +++ nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c | 318 ++ .../Xserver/hw/nxagent/X/NXmiglyph.c.NX.original | 318 ++ .../Xserver/hw/nxagent/X/NXmiglyph.c.X.original | 243 + nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c | 233 + .../Xserver/hw/nxagent/X/NXmitrap.c.NX.original | 233 + .../Xserver/hw/nxagent/X/NXmitrap.c.X.original | 190 + nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c | 1222 ++++ .../Xserver/hw/nxagent/X/NXmiwindow.c.NX.original | 1222 ++++ .../Xserver/hw/nxagent/X/NXmiwindow.c.X.original | 1184 ++++ nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c | 2220 ++++++++ .../Xserver/hw/nxagent/X/NXpicture.c.NX.original | 2220 ++++++++ .../Xserver/hw/nxagent/X/NXpicture.c.X.original | 1864 +++++++ .../programs/Xserver/hw/nxagent/X/NXpicturestr.h | 678 +++ .../hw/nxagent/X/NXpicturestr.h.NX.original | 678 +++ .../Xserver/hw/nxagent/X/NXpicturestr.h.X.original | 654 +++ nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c | 904 +++ .../Xserver/hw/nxagent/X/NXproperty.c.NX.original | 904 +++ .../Xserver/hw/nxagent/X/NXproperty.c.X.original | 729 +++ nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c | 1344 +++++ .../Xserver/hw/nxagent/X/NXrandr.c.NX.original | 1344 +++++ .../Xserver/hw/nxagent/X/NXrandr.c.X.original | 1319 +++++ nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c | 3799 +++++++++++++ .../Xserver/hw/nxagent/X/NXrender.c.NX.original | 3799 +++++++++++++ .../Xserver/hw/nxagent/X/NXrender.c.X.original | 3306 +++++++++++ nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c | 1173 ++++ .../Xserver/hw/nxagent/X/NXresource.c.NX.original | 1173 ++++ .../Xserver/hw/nxagent/X/NXresource.c.X.original | 954 ++++ nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c | 1455 +++++ .../Xserver/hw/nxagent/X/NXshm.c.NX.original | 1455 +++++ .../Xserver/hw/nxagent/X/NXshm.c.X.original | 1267 +++++ nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c | 4174 ++++++++++++++ .../Xserver/hw/nxagent/X/NXwindow.c.NX.original | 4174 ++++++++++++++ .../Xserver/hw/nxagent/X/NXwindow.c.X.original | 3853 +++++++++++++ nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c | 2286 ++++++++ .../Xserver/hw/nxagent/X/NXxvdisp.c.NX.original | 2286 ++++++++ .../Xserver/hw/nxagent/X/NXxvdisp.c.X.original | 2217 ++++++++ nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm | 41 + nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm | 48 + nx-X11/programs/Xserver/hw/nxagent/os2Stub.c | 402 ++ nx-X11/programs/Xserver/hw/nxagent/screensaver | 703 +++ 225 files changed, 263307 insertions(+) create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Agent.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Args.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Args.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Atoms.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Atoms.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Binder.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Binder.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/CHANGELOG create mode 100644 nx-X11/programs/Xserver/hw/nxagent/COPYING create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Client.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Client.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Clipboard.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Clipboard.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Colormap.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Colormap.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Composite.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Composite.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Cursor.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Cursor.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Dialog.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Dialog.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Display.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Display.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Drawable.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Drawable.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Error.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Error.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Events.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Events.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Extensions.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Extensions.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Font.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Font.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/GC.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/GCOps.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/GCOps.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/GCs.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Handlers.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Handlers.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Holder.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Holder.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Icons.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Image.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Image.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Imakefile create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Init.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Init.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Keyboard.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Keyboard.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Keystroke.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Keystroke.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/LICENSE create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Literals.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Millis.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Millis.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXcomposite.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXcomposite.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXcompositeint.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXcompositeproto.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXdamage.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXevents.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXevents.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXevents.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXextension.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXextension.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXextension.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglxext.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyph.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXpicture.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXproperty.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXrandr.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXrender.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXrender.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXrender.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXresource.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXresource.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXresource.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXshm.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXshm.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXshm.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXwindow.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXxrandr.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXxrandr.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXxrandrint.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.XF86.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Options.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Options.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Pixels.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Pixels.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Pixmap.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Pointer.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Pointer.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Reconnect.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Reconnect.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Render.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Render.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Rootless.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Rootless.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Screen.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Screen.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Splash.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Splash.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Split.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Split.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/TestExt.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Trap.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Trap.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Utils.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Visual.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Visual.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Window.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/Windows.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.NX.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.X.original create mode 100644 nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm create mode 100644 nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm create mode 100644 nx-X11/programs/Xserver/hw/nxagent/os2Stub.c create mode 100644 nx-X11/programs/Xserver/hw/nxagent/screensaver (limited to 'nx-X11/programs/Xserver/hw/nxagent') diff --git a/nx-X11/programs/Xserver/hw/nxagent/Agent.h b/nx-X11/programs/Xserver/hw/nxagent/Agent.h new file mode 100644 index 000000000..f976fd768 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Agent.h @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright (c) 1995 X Consortium + +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 X CONSORTIUM 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 X Consortium 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 X Consortium. + +*/ + +#ifndef __Agent_H__ +#define __Agent_H__ + +/* + * Machines with a 64 bit library interface and a 32 bit + * server require name changes to protect the guilty. + */ + +#ifdef _XSERVER64 +#define _XSERVER64_tmp +#undef _XSERVER64 +typedef unsigned long XID64; +typedef unsigned long Mask64; +typedef unsigned long Atom64; +typedef unsigned long VisualID64; +typedef unsigned long Time64; +#define XID XID64 +#define Mask Mask64 +#define Atom Atom64 +#define VisualID VisualID64 +#define Time Time64 +typedef XID Window64; +typedef XID Drawable64; +typedef XID Font64; +typedef XID Pixmap64; +typedef XID Cursor64; +typedef XID Colormap64; +typedef XID GContext64; +typedef XID KeySym64; +#define Window Window64 +#define Drawable Drawable64 +#define Font Font64 +#define Pixmap Pixmap64 +#define Cursor Cursor64 +#define Colormap Colormap64 +#define GContext GContext64 +#define KeySym KeySym64 + +#define XlibAtom Atom64 +#define XlibWindow Window64 +#define XlibPixmap Pixmap64 +#define XlibFont Font64 +#define XlibKeySym KeySym64 +#define XlibXID XID64 + +#else /*_XSERVER64*/ + +#define XlibAtom Atom +#define XlibWindow Window +#define XlibPixmap Pixmap +#define XlibFont Font +#define XlibKeySym KeySym +#define XlibXID XID + +#endif /*_XSERVER64*/ + +#define NX_TRANS_SOCKET +#define GC XlibGC +#include "Xlib.h" +#include "X11/extensions/shape.h" +#undef GC + +#ifdef _XSERVER64_tmp +#define _XSERVER64 +#undef _XSERVER64_tmp +#undef XID +#undef Mask +#undef Atom +#undef VisualID +#undef Time +#undef Window +#undef Drawable +#undef Font +#undef Pixmap +#undef Cursor +#undef Colormap +#undef GContext +#undef KeySym +#endif /*_XSERVER64_tmp*/ + +#define validateString(string) ((string) ? (string) : "(null)") + +#endif /* __Agent_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.c b/nx-X11/programs/Xserver/hw/nxagent/Args.c new file mode 100644 index 000000000..07526de56 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Args.c @@ -0,0 +1,2357 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include +#include +#include + +#ifdef __sun +#include +#endif + +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "dixstruct.h" +#include "servermd.h" +#include "opaque.h" + +#include "Agent.h" +#include "Display.h" +#include "Args.h" +#include "Options.h" +#include "Binder.h" +#include "Trap.h" +#include "Screen.h" +#include "Image.h" +#ifdef RENDER +#include "Render.h" +#endif +#include "Handlers.h" +#include "Error.h" + +/* + * NX includes and definitions. + */ + +#include "NXlib.h" +#include "NXpack.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef WATCH + +#ifdef WATCH + +#include "unistd.h" + +#endif + +/* + * Define this to force the dispatcher + * to always use the dumb scheduler. + */ + +#undef DISABLE_SMART_SCHEDULE + +int nxagentUserDefinedFontPath = 0; + +/* + * From X11/ImUtil.c. + */ + +extern int _XGetBitsPerPixel(Display *dpy, int depth); + +extern char dispatchExceptionAtReset; + +char nxagentDisplayName[1024]; + +char nxagentShadowDisplayName[1024] = {0}; + +char nxagentWindowName[256]; +char nxagentDialogName[256]; +char nxagentSessionId[256] = {0}; +char *nxagentOptionFile; + +Bool nxagentFullGeneration = False; +int nxagentDefaultClass = TrueColor; +Bool nxagentUserDefaultClass = False; +int nxagentDefaultDepth; +Bool nxagentUserDefaultDepth = False; +struct UserGeometry nxagentUserGeometry = {0, 0, 0, 0, 0}; +Bool nxagentUserBorderWidth = False; +int nxagentNumScreens = 0; +Bool nxagentDoDirectColormaps = False; +Window nxagentParentWindow = 0; +Bool nxagentIpaq = False; + +int nxagentLockDeferLevel = 0; + +Bool nxagentResizeDesktopAtStartup = False; + +Bool nxagentUseNXTrans = False; +Bool nxagentForceNXTrans = False; + +int nxagentMaxAllowedResets = 0; + +char *nxagentKeyboard = NULL; + +Bool nxagentOnce = True; + +static void nxagentParseOptionString(char*); + +/* + * Get the caption to be used for helper dialogs + * from agent's window name passed as parameter. + */ + +static int nxagentGetDialogName(void); + +char nxagentVerbose = 0; + +int ddxProcessArgument(int argc, char *argv[], int i) +{ + /* + * Ensure that the options are set to their defaults. + */ + + static Bool resetOptions = True; + + if (resetOptions == True) + { + char *envOptions = NULL; + char *envDisplay = NULL; + int j; + + nxagentInitOptions(); + + resetOptions = False; + + /* + * Ensure the correct order of options evaluation: + * the environment first, then those included in + * the options file and, last, the command line + * options. + */ + + envDisplay = getenv("DISPLAY"); + + if (envDisplay != NULL && strlen(envDisplay) == 0) + { + envDisplay = NULL; + } + + for (j = 0; j < argc; j++) + { + if ((!strcmp(argv[j], "-display")) && (j + 1 < argc)) + { + envOptions = malloc(strlen(argv[j + 1]) + 1); + + if (envOptions != NULL) + { + envOptions = strcpy(envOptions, argv[j + 1]); + } + #ifdef WARNING + else + { + fprintf(stderr, "ddxProcessArgument: WARNING! failed string allocation.\n"); + } + #endif + + break; + } + } + + if ((envOptions == NULL) && (envDisplay != NULL)) + { + envOptions = malloc(strlen(envDisplay) + 1); + + if (envOptions != NULL) + { + envOptions = strcpy(envOptions, envDisplay); + } + #ifdef WARNING + else + { + fprintf(stderr, "ddxProcessArgument: WARNING! failed string allocation.\n"); + } + #endif + } + + if (envOptions != NULL) + { + nxagentParseOptionString(envOptions); + + free(envOptions); + } + + for (j = 0; j < argc; j++) + { + if ((!strcmp(argv[j], "-options") || !strcmp(argv[j], "-option")) && j + 1 < argc) + { + if (nxagentOptionFile) + { + nxagentOptionFile = (char *) realloc(nxagentOptionFile, strlen(argv[j + 1]) + 1); + } + else + { + nxagentOptionFile = (char *) malloc(strlen(argv[j + 1]) +1); + } + + if (nxagentOptionFile != NULL) + { + nxagentOptionFile = strcpy(nxagentOptionFile, argv[j + 1]); + } + #ifdef WARNING + else + { + fprintf(stderr, "ddxProcessArgument: WARNING! failed string allocation.\n"); + } + #endif + + break; + } + } + + if (nxagentOptionFile) + { + nxagentProcessOptionsFile(); + } + } + + if (!strcmp(argv[i], "-B")) + { + #ifdef TEST + fprintf(stderr, "ddxProcessArgument: Checking the NX binder option.\n"); + #endif + + if (nxagentCheckBinder(argc, argv, i) > 0) + { + /* + * We are going to run the agent with the + * 'binder' option. Go straight to the + * proxy loop. + */ + + #ifdef TEST + fprintf(stderr, "ddxProcessArgument: Entering the NX proxy binder loop.\n"); + #endif + + nxagentBinderLoop(); + + /* + * This will make an exit. + */ + + nxagentBinderExit(0); + } + else + { + /* + * Exit with an error. + */ + + nxagentBinderExit(1); + } + } + + if (!strcmp(argv[i], "-display")) + { + if (++i < argc) + { + strncpy(nxagentDisplayName, argv[i], 1023); + + nxagentDisplayName[1023] = '\0'; + + return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-id")) + { + if (++i < argc) + { + strncpy(nxagentSessionId, argv[i], 255); + + *(nxagentSessionId + 255) = '\0'; + + return 2; + } + + return 0; + } + + /* + * This had to be '-options' since the beginning + * but was '-option' by mistake. Now we have to + * handle the backward compatibility. + */ + + if (!strcmp(argv[i], "-options") || !strcmp(argv[i], "-option")) + { + if (++i < argc) + { + int size; + + if (nxagentOptionFile != NULL) + { + xfree(nxagentOptionFile); + + nxagentOptionFile = NULL; + } + + if ((size = strlen(argv[i])) < 1024) + { + if ((nxagentOptionFile = xalloc(size + 1)) == NULL) + { + FatalError("malloc failed"); + } + + strncpy(nxagentOptionFile, argv[i], size); + + nxagentOptionFile[size] = '\0'; + } + else + { + /* + * It is useless to store the file name + * that has just been truncated. + */ + + #ifdef WARNING + fprintf(stderr, "ddxProcessArgument: WARNING! Option file name " + "too long. It will be ignored.\n"); + #endif + } + + return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-full")) { + nxagentFullGeneration = True; + return 1; + } + + if (!strcmp(argv[i], "-class")) { + if (++i < argc) { + if (!strcmp(argv[i], "StaticGray")) { + nxagentDefaultClass = StaticGray; + nxagentUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "GrayScale")) { + nxagentDefaultClass = GrayScale; + nxagentUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "StaticColor")) { + nxagentDefaultClass = StaticColor; + nxagentUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "PseudoColor")) { + nxagentDefaultClass = PseudoColor; + nxagentUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "TrueColor")) { + nxagentDefaultClass = TrueColor; + nxagentUserDefaultClass = True; + return 2; + } + else if (!strcmp(argv[i], "DirectColor")) { + nxagentDefaultClass = DirectColor; + nxagentUserDefaultClass = True; + return 2; + } + } + return 0; + } + + if (!strcmp(argv[i], "-cc")) { + if (++i < argc && sscanf(argv[i], "%i", &nxagentDefaultClass) == 1) { + if (nxagentDefaultClass >= 0 && nxagentDefaultClass <= 5) { + nxagentUserDefaultClass = True; + /* lex the OS layer process it as well, so return 0 */ + } + } + return 0; + } + + if (!strcmp(argv[i], "-depth")) { + if (++i < argc && sscanf(argv[i], "%i", &nxagentDefaultDepth) == 1) { + if (nxagentDefaultDepth > 0) { + nxagentUserDefaultDepth = True; + return 2; + } + } + return 0; + } + + /* + * These options are now useless and are + * parsed only for compatibility with + * older versions. + */ + + if (!strcmp(argv[i], "-fast") || + !strcmp(argv[i], "-slow") || + !strcmp(argv[i], "-hint") || + !strcmp(argv[i], "-sss")) + { + fprintf(stderr, "Warning: Ignoring deprecated command line option '%s'.\n", + argv[i]); + + return 1; + } + + if (!strcmp(argv[i], "-backingstore")) + { + if (++i < argc) + { + if (!strcmp(argv[i], "0")) + { + nxagentChangeOption(BackingStore, BackingStoreNever); + } + else + { + nxagentChangeOption(BackingStore, BackingStoreForce); + } + + return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-streaming")) + { + if (++i < argc) + { + if (!strcmp(argv[i], "0")) + { + nxagentChangeOption(Streaming, 0); + } + else + { + nxagentChangeOption(Streaming, 1); + } + + return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-defer")) + { + int level; + + if (++i < argc && + sscanf(argv[i], "%i", &level) == 1 && + level >= 0 && level <= 2) + { + if (nxagentOption(Shadow) == 0) + { + nxagentChangeOption(DeferLevel, level); + + /* + * The defer level set with the command + * line is not changed when the session + * is resumed. + */ + + nxagentLockDeferLevel = 1; + } + + return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-tile")) + { + int width; + int height; + + if (++i < argc && + sscanf(argv[i], "%ix%i", &width, &height) == 2 && + width >= 32 && height >= 32) + { + nxagentChangeOption(TileWidth, width); + nxagentChangeOption(TileHeight, height); + + return 2; + } + + return 0; + } + + if (strcmp(argv[i], "-fp") == 0) + { + if(++i < argc) + { + + #ifdef sgi + + userdefinedfontpath = 1; + + #endif + + #ifdef TEST + fprintf(stderr, "ddxProcessArgument: User defined font path [%s].\n", argv[i]); + #endif + + nxagentUserDefinedFontPath = 1; + + defaultFontPath = argv[i]; + } + else + { + UseMsg(); + } + } + + if (!strcmp(argv[i], "-geometry")) + { + if (++i < argc) + { + if (!strcmp(argv[i],"fullscreen")) + { + nxagentChangeOption(Fullscreen, True); + } + else if (!strcmp(argv[i],"ipaq")) + { + nxagentChangeOption(Fullscreen, True); + + nxagentIpaq = True; + } + else + { + if (nxagentUserGeometry.flag == 0) + { + nxagentUserGeometry.flag = XParseGeometry(argv[i], + &nxagentUserGeometry.X, + &nxagentUserGeometry.Y, + &nxagentUserGeometry.Width, + &nxagentUserGeometry.Height); + } + } + + if (nxagentUserGeometry.flag || (nxagentOption(Fullscreen) == 1)) return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-bw")) + { + int BorderWidth; + + if (++i < argc && sscanf(argv[i], "%i", &BorderWidth) == 1) + { + nxagentChangeOption(BorderWidth, BorderWidth); + + if (nxagentOption(BorderWidth) >= 0) + { + nxagentUserBorderWidth = True; + + return 2; + } + } + + return 0; + } + + if (!strcmp(argv[i], "-name")) + { + if (++i < argc) + { + strncpy(nxagentWindowName, argv[i], 255); + + *(nxagentWindowName + 255) = '\0'; + + return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-scrns")) { + if (++i < argc && sscanf(argv[i], "%i", &nxagentNumScreens) == 1) { + if (nxagentNumScreens > 0) { + if (nxagentNumScreens > MAXSCREENS) { + ErrorF("Maximum number of screens is %d.\n", MAXSCREENS); + nxagentNumScreens = MAXSCREENS; + } + return 2; + } + } + return 0; + } + + if (!strcmp(argv[i], "-install")) { + nxagentDoDirectColormaps = True; + return 1; + } + + if (!strcmp(argv[i], "-parent")) { + if (++i < argc) { + nxagentParentWindow = (XID) strtol (argv[i], (char**)NULL, 0); + return 2; + } + } + + if (!strcmp(argv[i], "-forcenx")) { + nxagentForceNXTrans = True; + return 1; + } + + if (!strcmp(argv[i], "-noonce")) + { + nxagentOnce = False; + return 1; + } + + if (!strcmp(argv[i], "-kbtype") || + !strcmp(argv[i], "-keyboard")) + { + if (++i < argc) + { + int size; + + if (nxagentKeyboard != NULL) + { + xfree(nxagentKeyboard); + + nxagentKeyboard = NULL; + } + + if ((size = strlen(argv[i])) < 256) + { + if ((nxagentKeyboard = xalloc(size + 1)) == NULL) + { + FatalError("malloc failed"); + } + + strncpy(nxagentKeyboard, argv[i], size); + + nxagentKeyboard[size] = '\0'; + } + #ifdef WARNING + else + { + /* + * it is useless to remember a kbtype + * option that has just been truncated. + */ + + fprintf(stderr, "ddxProcessArgument: WARNING! Option [%s] too long. " + "It will be ignored.\n", argv[i]); + } + #endif + + return 2; + } + + return 0; + } + + if (!strcmp(argv[i], "-extensions")) + { + return 1; + } + + #ifdef RENDER + if (!strcmp(argv[i], "-norender")) + { + nxagentRenderEnable = False; + + return 1; + } + #endif + + if (!strcmp(argv[i], "-nocomposite")) + { + nxagentChangeOption(Composite, 0); + + return 1; + } + + if (!strcmp(argv[i], "-nodamage")) + { + nxagentChangeOption(UseDamage, 0); + + return 1; + } + + /* + * The original -noreset option, disabling + * dispatchExceptionAtReset, is the default. + * Use this option to restore the original + * behaviour. + */ + + if (!strcmp(argv[i], "-reset")) + { + nxagentChangeOption(Reset, True); + + return 1; + } + + if (!strcmp(argv[i], "-persistent")) + { + nxagentChangeOption(Persistent, True); + + return 1; + } + + if (!strcmp(argv[i], "-nopersistent")) + { + nxagentChangeOption(Persistent, False); + + return 1; + } + + if (!strcmp(argv[i], "-noshmem")) + { + nxagentChangeOption(SharedMemory, False); + + return 1; + } + + if (!strcmp(argv[i], "-shmem")) + { + nxagentChangeOption(SharedMemory, True); + + return 1; + } + + if (!strcmp(argv[i], "-noignore")) + { + nxagentChangeOption(DeviceControl, True); + + return 1; + } + + if (!strcmp(argv[i], "-nokbreset")) + { + nxagentChangeOption(ResetKeyboardAtResume, False); + + return 1; + } + + if (!strcmp(argv[i], "-noxkblock")) + { + nxagentChangeOption(InhibitXkb, 0); + + return 1; + } + + /* + * Enable pseudo-rootless mode. + */ + + if (!strcmp(argv[i], "-R")) + { + if (nxagentOption(Binder) == UNDEFINED || + nxagentOption(Desktop) == UNDEFINED || + nxagentOption(Rootless) == UNDEFINED) + { + nxagentChangeOption(Binder, False); + nxagentChangeOption(Desktop, False); + nxagentChangeOption(Rootless, True); + } + return 1; + } + + /* + * Enable the "desktop" mode. This is + * the default. + */ + + if (!strcmp(argv[i], "-D")) + { + nxagentChangeOption(Binder, False); + nxagentChangeOption(Rootless, False); + nxagentChangeOption(Desktop, True); + + return 1; + } + + /* + * Enable the "shadow" mode. + */ + + if (!strcmp(argv[i], "-S")) + { + nxagentChangeOption(Shadow, 1); + nxagentChangeOption(DeferLevel, 0); + nxagentChangeOption(Persistent, 0); + + return 1; + } + + if (!strcmp(argv[i], "-shadow")) + { + if (++i < argc) + { + strncpy(nxagentShadowDisplayName, argv[i], 1023); + + if (strcmp(nxagentShadowDisplayName, "") == 0) + { + FatalError("Invalid shadow display option"); + } + + *(nxagentShadowDisplayName + 1023) = '\0'; + + return 2; + } + + return 0; + } + + + if (!strcmp(argv[i], "-shadowmode")) + { + if (++i < argc) + { + if (!strcmp(argv[i], "0")) + { + nxagentChangeOption(ViewOnly, 1); + } + else + { + nxagentChangeOption(ViewOnly, 0); + } + + return 2; + } + + return 0; + } + + /* + * Enable the auto-disconnect timeout. + */ + + if (!strcmp(argv[i], "-timeout")) + { + int seconds; + + if (++i < argc && sscanf(argv[i], "%i", &seconds) == 1) + { + if (seconds >= 0) + { + if (seconds > 0 && seconds < 60) + { + seconds = 60; + } + + nxagentChangeOption(Timeout, seconds); + + return 2; + } + } + + return 0; + } + + /* + * The return value for -query, -broadcast and + * -indirect must be 0 to let the dix layer pro- + * cess these options. + */ + + if (!strcmp(argv[i], "-query")) + + { + nxagentChangeOption(Desktop, True); + nxagentChangeOption(Xdmcp, True); + + nxagentMaxAllowedResets = 0; + + return 0; + } + + if (!strcmp(argv[i], "-broadcast")) + + { + nxagentChangeOption(Desktop, True); + nxagentChangeOption(Xdmcp, True); + + nxagentMaxAllowedResets = 0; + + return 0; + } + + if (!strcmp(argv[i], "-indirect")) + { + nxagentChangeOption(Desktop, True); + nxagentChangeOption(Xdmcp, True); + + nxagentMaxAllowedResets = 1; + + return 0; + } + + if (!strcmp(argv[i], "-noshpix")) + { + nxagentChangeOption(SharedPixmaps, False); + + return 1; + } + + if (!strcmp(argv[i], "-shpix")) + { + nxagentChangeOption(SharedPixmaps, True); + + return 1; + } + + if (!strcmp(argv[i], "-clipboard")) + { + if (!strcmp(argv[i+1], "both")) + { + nxagentChangeOption(Clipboard, ClipboardBoth); + } + else if (!strcmp(argv[i+1], "client")) + { + nxagentChangeOption(Clipboard, ClipboardClient); + } + else if (!strcmp(argv[i+1], "server")) + { + nxagentChangeOption(Clipboard, ClipboardServer); + } + else if (!strcmp(argv[i+1], "none")) + { + nxagentChangeOption(Clipboard, ClipboardNone); + } + else + { + nxagentChangeOption(Clipboard, ClipboardBoth); + } + + return 2; + } + + if (!strcmp(argv[i], "-bs")) + { + nxagentChangeOption(BackingStore, BackingStoreNever); + return 1; + } + + if (!strcmp(argv[i], "-verbose")) + { + nxagentVerbose = 1; + + return 1; + } + + return 0; +} + +static void nxagentParseOptions(char *name, char *value) +{ + int size, argc; + + char *argv[2] = { NULL, NULL }; + + #ifdef TEST + fprintf(stderr, "nxagentParseOptions: Processing option '%s' = '%s'.\n", + validateString(name), validateString(value)); + #endif + + if (!strcmp(name, "kbtype") || + !strcmp(name, "keyboard") || + !strcmp(name, "id") || + !strcmp(name, "display") || + !strcmp(name, "clipboard") || + !strcmp(name, "geometry") || + !strcmp(name, "option") || + !strcmp(name, "options") || + !strcmp(name, "shadow") || + !strcmp(name, "shadowmode") || + !strcmp(name, "streaming") || + !strcmp(name, "defer") || + !strcmp(name, "tile")) + { + argv[1] = value; + + argc = 2; + } + else if (!strcmp(name, "R") && !strcmp(value, "1")) + { + argc = 1; + } + else if (!strcmp(name, "fast") || !strcmp(name, "slow")) + { + fprintf(stderr, "Warning: Ignoring deprecated option '%s'.\n", name); + + return; + } + else if (!strcmp(name, "render")) + { + if (nxagentReconnectTrap == True) + { + #ifdef DEBUG + fprintf(stderr, "nxagentParseOptions: Ignoring option 'render' at reconnection.\n"); + #endif + } + else if (nxagentRenderEnable == UNDEFINED) + { + if (!strcmp(value, "1")) + { + nxagentRenderEnable = True; + } + else if (!strcmp(value, "0")) + { + nxagentRenderEnable = False; + } + else + { + fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'render'.\n", + validateString(value)); + } + } + + return; + } + else if (!strcmp(name, "fullscreen")) + { + if (nxagentReconnectTrap == True) + { + #ifdef DEBUG + fprintf(stderr, "nxagentParseOptions: Ignoring option 'fullscreen' at reconnection.\n"); + #endif + } + else if (!strcmp(value, "1")) + { + nxagentChangeOption(Fullscreen, True); + } + else if (!strcmp(value, "0")) + { + nxagentChangeOption(Fullscreen, False); + } + else + { + fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'fullscreen'.\n", + validateString(value)); + } + + return; + } + else if (!strcmp(name, "shpix")) + { + if (!strcmp(value, "1")) + { + nxagentChangeOption(SharedPixmaps, True); + } + else if (!strcmp(value, "0")) + { + nxagentChangeOption(SharedPixmaps, False); + } + else + { + fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'shpix'.\n", + validateString(value)); + } + + return; + } + else if (!strcmp(name, "shmem")) + { + if (!strcmp(value, "1")) + { + nxagentChangeOption(SharedMemory, True); + } + else if (!strcmp(value, "0")) + { + nxagentChangeOption(SharedMemory, False); + } + else + { + fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'shmem'.\n", + validateString(value)); + } + + return; + } + else if (!strcmp(name, "composite")) + { + if (!strcmp(value, "1")) + { + nxagentChangeOption(Composite, 1); + } + else if (!strcmp(value, "0")) + { + nxagentChangeOption(Composite, 0); + } + else + { + fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'composite'.\n", + validateString(value)); + } + + return; + } + else if (!strcmp(name, "resize")) + { + if (!strcmp(value, "1")) + { + nxagentResizeDesktopAtStartup = True; + } + else if (!strcmp(value, "0")) + { + nxagentResizeDesktopAtStartup = False; + } + else + { + fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'resize'.\n", + validateString(value)); + } + + return; + } + else if (!strcmp(name, "backingstore")) + { + if (!strcmp(value, "0")) + { + nxagentChangeOption(BackingStore, BackingStoreNever); + } + else + { + nxagentChangeOption(BackingStore, BackingStoreForce); + } + + return; + } + else if (!strcmp(name, "menu")) + { + if (!strcmp(value, "0")) + { + nxagentChangeOption(Menu, 0); + } + else + { + nxagentChangeOption(Menu, 1); + } + + return; + } + else if (strcmp(name, "shadowuid") == 0) + { + nxagentShadowUid = atoi(value); + + return; + } + else if (strcmp(name, "clients") == 0) + { + strcpy(nxagentClientsLogName, value); + + return; + } + else if (strcmp(name, "client") == 0) + { + if (strcmp(value, "winnt") == 0 || strcmp(value, "windows") == 0) + { + nxagentChangeOption(ClientOs, ClientOsWinnt); + } + else if (strcmp(value, "linux") == 0) + { + nxagentChangeOption(ClientOs, ClientOsLinux); + } + else if (strcmp(value, "solaris") == 0) + { + nxagentChangeOption(ClientOs, ClientOsSolaris); + } + else if (strcmp(value, "mac") == 0) + { + nxagentChangeOption(ClientOs, ClientOsMac); + } + + return; + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentParseOptions: Ignored option [%s] with value [%s].\n", + validateString(name), validateString(value)); + #endif + + return; + } + + /* + * Before passing the not yet evaluated options + * to ddxProcessArgument(), we have to add a dash + * as prefix. + */ + + if ((size = strlen(name) + 1) > 1) + { + if ((argv[0] = malloc(size + 1)) == NULL) + { + fprintf(stderr, "Warning: Ignoring option '%s' due to lack of memory.\n", + name); + + return; + } + + *argv[0] = '-'; + + memcpy(argv[0] + 1, name, size); + } + + ddxProcessArgument(argc, argv, 0); + + free(argv[0]); +} + +static void nxagentParseOptionString(char *string) +{ + char *value = NULL; + char *option = NULL; + char *delimiter = NULL; + + /* + * Remove the port specification. + */ + + delimiter = rindex(string, ':'); + + if (delimiter) + { + *delimiter = 0; + } + else + { + fprintf(stderr, "Warning: Option file doesn't contain a port specification.\n"); + } + + while ((option = strtok(option ? NULL : string, ","))) + { + delimiter = rindex(option, '='); + + if (delimiter) + { + *delimiter = 0; + value = delimiter + 1; + } + else + { + value = NULL; + } + + nxagentParseOptions(option, value); + } +} + +void nxagentProcessOptionsFile() +{ + FILE *file; + char *data; + + int offset; + int size; + + int sizeOfFile; + int maxFileSize = 1024; + + #ifdef DEBUG + fprintf(stderr, "nxagentProcessOptionsFile: Going to process option the file [%s].\n", + validateString(nxagentOptionFile)); + #endif + + if (nxagentOptionFile == NULL) + { + return; + } + + if ((file = fopen(nxagentOptionFile, "r")) == NULL) + { + fprintf(stderr, "Warning: Couldn't open option file '%s'. Error is '%s'.\n", + validateString(nxagentOptionFile), strerror(errno)); + + goto nxagentProcessOptionsFileExit; + } + + if (fseek(file, 0, SEEK_END) != 0) + { + fprintf(stderr, "Warning: Couldn't position inside option file '%s'. Error is '%s'.\n", + validateString(nxagentOptionFile), strerror(errno)); + + goto nxagentProcessOptionsFileClose; + } + + if ((sizeOfFile = ftell(file)) == -1) + { + fprintf(stderr, "Warning: Couldn't get the size of option file '%s'. Error is '%s'.\n", + validateString(nxagentOptionFile), strerror(errno)); + + goto nxagentProcessOptionsFileClose; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentProcessOptionsFile: Processing option file [%s].\n", + validateString(nxagentOptionFile)); + #endif + + rewind(file); + + if (sizeOfFile > maxFileSize) + { + fprintf(stderr, "Warning: Maximum file size exceeded for options '%s'.\n", + validateString(nxagentOptionFile)); + + goto nxagentProcessOptionsFileClose; + } + + if ((data = xalloc(sizeOfFile + 1)) == NULL) + { + fprintf(stderr, "Warning: Memory allocation failed processing file '%s'.\n", + validateString(nxagentOptionFile)); + + goto nxagentProcessOptionsFileClose; + } + + offset = 0; + size = 0; + + for (;;) + { + size_t result = fread(data + offset, 1, sizeOfFile, file); + + if (ferror(file) != 0) + { + fprintf(stderr, "Warning: Error reading the option file '%s'.\n", + validateString(nxagentOptionFile)); + + goto nxagentProcessOptionsFileFree; + } + + size += result; + offset += result; + + if (feof(file) != 0 || (size == sizeOfFile)) + { + break; + } + } + + if (size != sizeOfFile) + { + fprintf(stderr, "Warning: Premature end of option file '%s' while reading.\n", + validateString(nxagentOptionFile)); + + goto nxagentProcessOptionsFileFree; + } + + /* + * Truncate the buffer to the first line. + */ + + for (offset = 0; (offset < sizeOfFile) && (data[offset] != '\n'); offset++); + + data[offset] = 0; + + nxagentParseOptionString(data); + +nxagentProcessOptionsFileFree: + + if (data != NULL) + { + Xfree(data); + } + +nxagentProcessOptionsFileClose: + + if (fclose(file) != 0) + { + fprintf(stderr, "Warning: Couldn't close option file '%s'. Error is '%s'.\n", + validateString(nxagentOptionFile), strerror(errno)); + } + +nxagentProcessOptionsFileExit: + + return; +} + +/* + * FIXME: Transport initialization, shouldn't depend upon + * argv[], because we call it at every reconnection. + */ + +Bool nxagentPostProcessArgs(char* name, Display* dpy, Screen* scr) +{ + Bool useNXTrans = False; + + #ifdef WATCH + + fprintf(stderr, "nxagentPostProcessArgs: Watchpoint 2.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +N/A +*/ + + sleep(30); + + #endif + + if ((nxagentOption(Rootless) == 1) && nxagentOption(Fullscreen) == 1) + { + #ifdef TEST + fprintf(stderr, "WARNING: Ignoring fullscreen option for rootless session.\n"); + #endif + + nxagentChangeOption(Fullscreen, False); + } + + /* + * Ensure we have a valid name for children dialogs. + */ + + nxagentGetDialogName(); + + /* + * Ensure we have a valid name for window name. + */ + + if (*nxagentWindowName == '\0') + { + strncpy(nxagentWindowName, "NX", 255); + + *(nxagentWindowName + 255) = '\0'; + } + + /* + * Note that use of NX packed images as well as + * render extension could be later disabled due + * to the fact that session is running nested + * in a nxagent server. + */ + + if (nxagentForceNXTrans) + { + useNXTrans = True; + } + else if ((strncasecmp(name, "nx/", 3) == 0) || + (strncasecmp(name, "nx:", 3) == 0) || + (strncasecmp(name, "nx,", 3) == 0) || + (strcasecmp(name, "nx") == 0)) + { + useNXTrans = True; + } + + if (useNXTrans == True) + { + unsigned int linkType = LINK_TYPE_NONE; + + unsigned int localMajor = 0; + unsigned int localMinor = 0; + unsigned int localPatch = 0; + + unsigned int remoteMajor = 0; + unsigned int remoteMinor = 0; + unsigned int remotePatch = 0; + + int splitTimeout = 0; + int motionTimeout = 0; + + int splitMode = 0; + int splitSize = 0; + + unsigned int packMethod = PACK_NONE; + unsigned int packQuality = 9; + + int dataLevel = 0; + int streamLevel = 0; + int deltaLevel = 0; + + unsigned int loadCache = 0; + unsigned int saveCache = 0; + unsigned int startupCache = 0; + + unsigned int enableClient = 0; + unsigned int enableServer = 0; + + unsigned int clientSegment = 0; + unsigned int serverSegment = 0; + + unsigned int clientSize = 0; + unsigned int serverSize = 0; + + if (NXGetControlParameters(dpy, &linkType, &localMajor, &localMinor, + &localPatch, &remoteMajor, &remoteMinor, &remotePatch, + &splitTimeout, &motionTimeout, &splitMode, &splitSize, + &packMethod, &packQuality, &dataLevel, &streamLevel, + &deltaLevel, &loadCache, &saveCache, &startupCache) == 0) + { + fprintf(stderr, "Warning: Failed to get the control parameters.\n"); + } + + nxagentChangeOption(LinkType, linkType); + + #ifdef TEST + fprintf(stderr, "nxagentPostProcessArgs: Got local version [%d.%d.%d] remote version [%d.%d.%d].\n", + localMajor, localMinor, localPatch, remoteMajor, remoteMinor, remotePatch); + + fprintf(stderr, "nxagentPostProcessArgs: Got split timeout [%d] motion timeout [%d].\n", + splitTimeout, motionTimeout); + + fprintf(stderr, "nxagentPostProcessArgs: Got split mode [%d] split size [%d].\n", + splitMode, splitSize); + + fprintf(stderr, "nxagentPostProcessArgs: Got preferred pack method [%d] and quality [%d].\n", + packMethod, packQuality); + #endif + + if (remoteMajor < 2) + { + #ifdef TEST + fprintf(stderr, "nxagentPostProcessArgs: WARNING! Using backward compatible alpha encoding.\n"); + #endif + + nxagentAlphaCompat = 1; + } + else + { + nxagentAlphaCompat = 0; + } + + if (nxagentPackMethod == -1) + { + nxagentPackMethod = packMethod; + } + + if (nxagentPackQuality == -1) + { + nxagentPackQuality = packQuality; + } + + /* + * Set the minimum size of images being + * streamed. + */ + + if (nxagentSplitThreshold == -1) + { + nxagentSplitThreshold = splitSize; + } + + /* + * Let the remote proxy use the shared memory + * extension, if supported by the X server. + * The client part is not useful and not impl- + * emented. The size of the segment is chosen + * by the user. The only purpose of the message + * is to reserve the XID that will be used by + * the remote. + */ + + enableClient = 0; + enableServer = 1; + + if (NXGetShmemParameters(dpy, &enableClient, &enableServer, &clientSegment, + &serverSegment, &clientSize, &serverSize) == 0) + { + fprintf(stderr, "Warning: Failed to get the shared memory parameters.\n"); + } + + if (enableServer == 1) + { + fprintf(stderr, "Info: Using shared memory parameters %d/%d/%d/%dK.\n", + nxagentOption(SharedMemory), nxagentOption(SharedPixmaps), + enableServer, serverSize / 1024); + } + else + { + fprintf(stderr, "Info: Using shared memory parameters %d/%d/0/0K.\n", + nxagentOption(SharedMemory), nxagentOption(SharedPixmaps)); + } + + /* + * We don't need the NoExpose events. Block + * them at the proxy side. + */ + + NXSetExposeParameters(nxagentDisplay, 1, 1, 0); + } + else + { + /* + * We don't have a proxy on the remote side. + */ + + nxagentChangeOption(LinkType, LINK_TYPE_NONE); + } + + /* + * Set the lossless and lossy pack methods + * based on the user's preferences and the + * selected link type. + */ + + nxagentSetPackMethod(); + + /* + * If not set, set the defer level and the + * synchronization timeout based on the link + * type. + */ + + nxagentSetDeferLevel(); + + /* + * Also set the display output buffer size. + */ + + nxagentSetBufferSize(); + + /* + * Select the preferred scheduler. + */ + + nxagentSetScheduler(); + + /* + * Select the buffer coalescence timeout. + */ + + nxagentSetCoalescence(); + + /* + * Set the other defaults. + */ + + if (nxagentOption(Fullscreen) == UNDEFINED) + { + nxagentChangeOption(Fullscreen, False); + } + + if (nxagentOption(Binder) == UNDEFINED) + { + nxagentChangeOption(Binder, False); + } + + if (nxagentOption(Rootless) == UNDEFINED) + { + nxagentChangeOption(Rootless, False); + } + + if (nxagentOption(Desktop) == UNDEFINED) + { + nxagentChangeOption(Desktop, True); + } + + /* + * The enableBackingStore flag is defined + * in window.c in the dix. + */ +/* +FIXME: In rootless mode the backing-store support is not functional yet. +*/ + if (nxagentOption(Rootless)) + { + enableBackingStore = 0; + } + else if (nxagentOption(BackingStore) == BackingStoreUndefined || + nxagentOption(BackingStore) == BackingStoreForce) + { + enableBackingStore = 1; + } + else if (nxagentOption(BackingStore) == BackingStoreNever) + { + enableBackingStore = 0; + } + + /* + * need to check if this was set on the + * command line as this has the priority + * over the option file. + */ + + if (nxagentRenderEnable == UNDEFINED) + { + nxagentRenderEnable = True; + } + + if (nxagentRenderEnable == True) + { + nxagentAlphaEnabled = True; + } + else + { + nxagentAlphaEnabled = False; + } + + if ((nxagentOption(Rootless) == 1) && nxagentOption(Xdmcp)) + { + FatalError("PANIC! Cannot start a XDMCP session in rootless mode.\n"); + } + + /* + * We enable server reset only for indirect + * XDMCP sessions. + */ + + if (nxagentOption(Reset) == True && nxagentMaxAllowedResets == 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentPostProcessArgs: Disabling the server reset.\n"); + #endif + + nxagentChangeOption(Reset, False); + + dispatchExceptionAtReset = 0; + } + + /* + * We skip server reset by default. This should + * be equivalent to passing the -noreset option + * to a standard XFree86 server. + */ + + if (nxagentOption(Reset) == False) + { + #ifdef TEST + fprintf(stderr, "nxagentPostProcessArgs: Disabling dispatch of exception at server reset.\n"); + #endif + + dispatchExceptionAtReset = 0; + } + + /* + * Check if the user activated the auto-disconect + * feature. + */ + + if (nxagentOption(Timeout) > 0) + { + fprintf(stderr, "Info: Using auto-disconnect timeout of %d seconds.\n", + nxagentOption(Timeout)); + + nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND; + } + + #ifdef WATCH + + fprintf(stderr, "nxagentPostProcessArgs: Watchpoint 3.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#16 1 256 bits (0 KB) -> 12 bits (0 KB) -> 256/1 -> 12/1 = 21.333:1 +#233 A 1 256 bits (0 KB) -> 131 bits (0 KB) -> 256/1 -> 131/1 = 1.954:1 +#245 A 2 512 bits (0 KB) -> 19 bits (0 KB) -> 256/1 -> 10/1 = 26.947:1 +*/ + + sleep(30); + + #endif + + return useNXTrans; +} + +void ddxUseMsg() +{ + ErrorF("-display string display name of the real server\n"); + ErrorF("-sync synchronize with the real server\n"); + ErrorF("-full utilize full regeneration\n"); + ErrorF("-class string default visual class\n"); + ErrorF("-depth int default depth\n"); + ErrorF("-geometry WxH+X+Y window size and position\n"); + ErrorF("-bw int window border width\n"); + ErrorF("-name string window name\n"); + ErrorF("-scrns int number of screens to generate\n"); + ErrorF("-install install colormaps directly\n"); + + ErrorF("The NX system adds the following arguments:\n"); + ErrorF("-forcenx force use of NX protocol messages assuming communication through nxproxy\n"); + ErrorF("-timeout int auto-disconnect timeout in seconds (minimum allowed: 60)\n"); +#ifdef RENDER + ErrorF("-norender disable the use of the render extension\n"); + ErrorF("-nocomposite disable the use of the composite extension\n"); +#endif + ErrorF("-nopersistent disable disconnection/reconnection to the X display on SIGHUP\n"); + ErrorF("-noshmem disable use of shared memory extension\n"); + ErrorF("-shmem enable use of shared memory extension\n"); + ErrorF("-noshpix disable use of shared pixmaps\n"); + ErrorF("-shpix enable use of shared pixmaps\n"); + ErrorF("-noignore don't ignore pointer and keyboard configuration changes mandated by clients\n"); + ErrorF("-nokbreset don't reset keyboard device if the session is resumed\n"); + ErrorF("-noxkblock always allow applications to change layout through XKEYBOARD\n"); + ErrorF("-tile WxH size of image tiles (minimum allowed: 32x32)\n"); + ErrorF("-D enable desktop mode\n"); + ErrorF("-R enable rootless mode\n"); + ErrorF("-S enable shadow mode\n"); + ErrorF("-B enable proxy binding mode\n"); +} + +static int nxagentGetDialogName() +{ + strcpy(nxagentDialogName, "NX"); + + *(nxagentDialogName + 255) = '\0'; + + if (*nxagentSessionId != '\0') + { + int length = strlen(nxagentSessionId); + + strcpy(nxagentDialogName, "NX - "); + + if (length > (MD5_LENGTH * 2 + 1) && + *(nxagentSessionId + (length - (MD5_LENGTH * 2 + 1))) == '-') + { + strncat(nxagentDialogName, nxagentSessionId, length - (MD5_LENGTH * 2 + 1)); + } + else + { + strncat(nxagentDialogName, nxagentSessionId, 250); + } + + *(nxagentSessionId + 255) = '\0'; + + return 1; + } + + return 0; +} + +void nxagentSetPackMethod(void) +{ + unsigned char supportedMethods[NXNumberOfPackMethods]; + unsigned int entries = NXNumberOfPackMethods; + + int method; + + if (nxagentOption(LinkType) == LINK_TYPE_NONE) + { + nxagentChangeOption(Streaming, 0); + + nxagentPackMethod = PACK_NONE; + nxagentPackLossless = PACK_NONE; + + nxagentSplitThreshold = 0; + + return; + } + + /* + * Check if we need to select the lossy + * and lossless pack methods based on + * the link type. + */ + + method = nxagentPackMethod; + + if (method == PACK_ADAPTIVE) + { + #ifdef TEST + fprintf(stderr, "nxagentSetPackMethod: Using adaptive mode for image compression.\n"); + #endif + + nxagentChangeOption(Adaptive, 1); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentSetPackMethod: Not using adaptive mode for image compression.\n"); + #endif + + nxagentChangeOption(Adaptive, 0); + } + + if (method == PACK_LOSSY || method == PACK_ADAPTIVE) + { + nxagentPackMethod = PACK_JPEG_16M_COLORS; + } + else if (method == PACK_LOSSLESS) + { + switch (nxagentOption(LinkType)) + { + case LINK_TYPE_MODEM: + case LINK_TYPE_ISDN: + case LINK_TYPE_ADSL: + case LINK_TYPE_WAN: + { + nxagentPackMethod = PACK_BITMAP_16M_COLORS; + + break; + } + case LINK_TYPE_LAN: + { + nxagentPackMethod = PACK_RLE_16M_COLORS; + + break; + } + default: + { + fprintf(stderr, "Warning: Unknown link type '%d' while setting the pack method.\n", + nxagentOption(LinkType)); + + break; + } + } + } + + /* + * Query the remote proxy to determine + * whether the selected methods are + * supported. + */ + + if (NXGetUnpackParameters(nxagentDisplay, &entries, supportedMethods) == 0 || + entries != NXNumberOfPackMethods) + { + fprintf(stderr, "Warning: Unable to retrieve the supported pack methods.\n"); + + nxagentPackMethod = PACK_NONE; + nxagentPackLossless = PACK_NONE; + } + else + { + if (nxagentPackMethod == PACK_BITMAP_16M_COLORS || + nxagentPackMethod == PACK_RLE_16M_COLORS || + nxagentPackMethod == PACK_RGB_16M_COLORS || + nxagentPackMethod == PACK_NONE) + { + nxagentPackLossless = nxagentPackMethod; + } + else + { + if (nxagentOption(LinkType) == LINK_TYPE_LAN) + { + nxagentPackLossless = PACK_RLE_16M_COLORS; + } + else + { + nxagentPackLossless = PACK_BITMAP_16M_COLORS; + } + } + + if (supportedMethods[nxagentPackLossless] == 0) + { + nxagentPackLossless = PACK_NONE; + } + + #ifdef TEST + fprintf(stderr, "nxagentSetPackMethod: Using method [%d] for lossless compression.\n", + nxagentPackLossless); + #endif + + if (supportedMethods[nxagentPackMethod] == 0) + { + fprintf(stderr, "Warning: Pack method '%d' not supported by the proxy.\n", + nxagentPackMethod); + + fprintf(stderr, "Warning: Replacing with lossless pack method '%d'.\n", + nxagentPackLossless); + + nxagentPackMethod = nxagentPackLossless; + } + } + + if (nxagentPackMethod == nxagentPackLossless) + { + nxagentPackQuality = 9; + } + + #ifdef TEST + fprintf(stderr, "nxagentSetPackMethod: Assuming pack methods [%d] and [%d] with " + "quality [%d].\n", nxagentPackMethod, nxagentPackLossless, nxagentPackQuality); + #endif +} + +/* + * Each defer level adds the following rules to the previous ones: + * + * Level 0 Eager encoding. + * + * Level 1 No data is put or copied on pixmaps, marking them always + * as corrupted and synchronizing them on demand, i.e. when + * a copy area to a window is requested, the source is syn- + * chronized before copying it. + * + * Level 2 The put images over the windows are skipped marking the + * destination as corrupted. The same happens for copy area + * and composite operations, spreading the corrupted regions + * of involved drawables. + */ + +void nxagentSetDeferLevel() +{ + int deferLevel; + int tileWidth; + int tileHeight; + int deferTimeout; + + /* + * Streaming is only partly implemented + * and is not available in this version + * of the agent. + */ + + if (nxagentOption(Streaming) == 1) + { + fprintf(stderr, "Warning: Streaming of images not available in this agent.\n"); + + nxagentChangeOption(Streaming, 0); + } + + switch (nxagentOption(LinkType)) + { + case LINK_TYPE_MODEM: + { + deferLevel = 2; + + tileWidth = 64; + tileHeight = 64; + + deferTimeout = 200; + + break; + } + case LINK_TYPE_ISDN: + { + deferLevel = 2; + + tileWidth = 64; + tileHeight = 64; + + deferTimeout = 200; + + break; + } + case LINK_TYPE_ADSL: + { + deferLevel = 2; + + deferTimeout = 200; + + tileWidth = 65536; + tileHeight = 65536; + + break; + } + case LINK_TYPE_WAN: + { + deferLevel = 1; + + deferTimeout = 200; + + tileWidth = 65536; + tileHeight = 65536; + + break; + } + case LINK_TYPE_NONE: + case LINK_TYPE_LAN: + { + deferLevel = 0; + + deferTimeout = 200; + + tileWidth = 65536; + tileHeight = 65536; + + break; + } + default: + { + fprintf(stderr, "Warning: Unknown link type [%d] processing the defer option.\n", + nxagentOption(LinkType)); + + deferLevel = 0; + + tileWidth = 64; + tileHeight = 64; + + deferTimeout = 200; + + break; + } + } + + /* + * Set the defer timeout. + */ + + if (nxagentOption(Shadow) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Ignoring defer timeout parameter in shadow mode.\n"); + #endif + } + else + { + nxagentChangeOption(DeferTimeout, deferTimeout); + } + + /* + * Set the defer level. + */ + + if (nxagentOption(Shadow) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Ignoring defer parameter in shadow mode.\n"); + #endif + } + else if (nxagentOption(DeferLevel) != UNDEFINED) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Not overriding the [defer] option " + "with value [%d]. Defer timeout is [%ld] ms.\n", nxagentOption(DeferLevel), + nxagentOption(DeferTimeout)); + #endif + } + else + { + nxagentChangeOption(DeferLevel, deferLevel); + + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Assuming defer level [%d] with timeout of [%ld] ms.\n", + nxagentOption(DeferLevel), nxagentOption(DeferTimeout)); + #endif + } + + /* + * Set the tile width. + */ + + if (nxagentOption(TileWidth) != UNDEFINED) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Not overriding the [tile] option " + "width value [%d].\n", nxagentOption(TileWidth)); + #endif + } + else + { + nxagentChangeOption(TileWidth, tileWidth); + + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Assuming tile width [%d].\n", + nxagentOption(TileWidth)); + #endif + } + + /* + * Set the tile height. + */ + + if (nxagentOption(TileHeight) != UNDEFINED) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Not overriding the [tile] option " + "height value [%d].\n", nxagentOption(TileHeight)); + #endif + } + else + { + nxagentChangeOption(TileHeight, tileHeight); + + #ifdef TEST + fprintf(stderr, "nxagentSetDeferLevel: Assuming tile height [%d].\n", + nxagentOption(TileHeight)); + #endif + } +} + +void nxagentSetBufferSize() +{ + int size; + + switch (nxagentOption(LinkType)) + { + case LINK_TYPE_MODEM: + { + size = 4096; + + break; + } + case LINK_TYPE_ISDN: + { + size = 4096; + + break; + } + case LINK_TYPE_ADSL: + { + size = 8192; + + break; + } + case LINK_TYPE_WAN: + { + size = 16384; + + break; + } + case LINK_TYPE_NONE: + case LINK_TYPE_LAN: + { + size = 16384; + + break; + } + default: + { + fprintf(stderr, "Warning: Unknown link type '%d' while setting the display buffer size.\n", + nxagentOption(LinkType)); + + size = 16384; + + break; + } + } + + nxagentChangeOption(DisplayBuffer, size); + + nxagentBuffer = size; + + if (NXSetDisplayBuffer(nxagentDisplay, nxagentBuffer) < 0) + { + fprintf(stderr, "Warning: Can't set the display buffer size to [%d].\n", + nxagentBuffer); + } +} + +void nxagentSetScheduler() +{ + #ifdef DISABLE_SMART_SCHEDULE + + #ifdef SMART_SCHEDULE + + #ifdef TEST + fprintf(stderr, "nxagentSetScheduler: Disabling the smart scheduler.\n"); + #endif + + nxagentDisableTimer(); + + #endif + + #else /* #ifdef DISABLE_SMART_SCHEDULE */ + + /* + * The smart scheduler is the default. + */ + + #ifdef SMART_SCHEDULE + + if (nxagentOption(Shadow) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSetScheduler: Using the dumb scheduler in shadow mode.\n"); + #endif + + nxagentDisableTimer(); + } + + #endif + + #endif /* #ifdef DISABLE_SMART_SCHEDULE */ +} + +void nxagentSetCoalescence() +{ + int timeout; + + switch (nxagentOption(LinkType)) + { + case LINK_TYPE_MODEM: + { + timeout = 50; + + break; + } + case LINK_TYPE_ISDN: + { + timeout = 20; + + break; + } + case LINK_TYPE_ADSL: + { + timeout = 10; + + break; + } + case LINK_TYPE_WAN: + { + timeout = 5; + + break; + } + case LINK_TYPE_NONE: + case LINK_TYPE_LAN: + { + timeout = 0; + + break; + } + default: + { + fprintf(stderr, "Warning: Unknown link type '%d' while setting the display coalescence.\n", + nxagentOption(LinkType)); + + timeout = 0; + + break; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentSetCoalescence: Using coalescence timeout of [%d] ms.\n", + timeout); + #endif + + nxagentChangeOption(DisplayCoalescence, timeout); +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.h b/nx-X11/programs/Xserver/hw/nxagent/Args.h new file mode 100644 index 000000000..43d7ec779 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Args.h @@ -0,0 +1,84 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Args_H__ +#define __Args_H__ + +#define MD5_LENGTH 16 + +struct UserGeometry{ + int flag; + int X; + int Y; + unsigned int Width; + unsigned int Height; +}; + +extern Bool nxagentUseNXTrans; + +extern char nxagentSessionId[]; +extern char nxagentDisplayName[]; +extern char nxagentShadowDisplayName[]; +extern char nxagentWindowName[]; +extern char nxagentDialogName[]; + +extern Bool nxagentFullGeneration; +extern int nxagentDefaultClass; +extern Bool nxagentUserDefaultClass; +extern int nxagentDefaultDepth; +extern Bool nxagentUserDefaultDepth; +extern int nxagentX; +extern int nxagentY; +extern unsigned int nxagentWidth; +extern unsigned int nxagentHeight; +extern struct UserGeometry nxagentUserGeometry; +extern Bool nxagentUserBorderWidth; +extern int nxagentNumScreens; +extern Bool nxagentDoDirectColormaps; +extern Window nxagentParentWindow; +extern int nxagentMaxAllowedReset; +extern Bool nxagentResizeDesktopAtStartup; +extern Bool nxagentIpaq; + +extern int nxagentLockDeferLevel; + +Bool nxagentPostProcessArgs(char *name, Display *dpy, Screen *scr); +void nxagentProcessOptionsFile(void); + +void nxagentSetPackMethod(void); +void nxagentSetDeferLevel(void); +void nxagentSetBufferSize(void); +void nxagentSetScheduler(void); +void nxagentSetCoalescence(void); + +extern int nxagentUserDefinedFontPath; + +#endif /* __Args_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c new file mode 100644 index 000000000..1f412fd27 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c @@ -0,0 +1,785 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "scrnintstr.h" +#include "Agent.h" + +#include "Xutil.h" +#include "Xatom.h" +#include "Xlib.h" + +#include "misc.h" +#include "scrnintstr.h" +#include "resource.h" + +#include "NXpack.h" + +#include "Atoms.h" +#include "Args.h" +#include "Image.h" +#include "Display.h" +#include "Screen.h" +#include "Options.h" +#include "Agent.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * These values should be moved in + * the option repository. + */ + +Bool nxagentWMIsRunning; + +static void startWMDetection(void); + +static int nxagentInitAtomMap(char **atomNameList, int count, Atom *atomsRet); + +#ifdef DEBUG +static void nxagentPrintAtomMapInfo(char *message); +#else +#define nxagentPrintAtomMapInfo(arg) +#endif + +Atom nxagentAtoms[NXAGENT_NUMBER_OF_ATOMS]; + +static char *nxagentAtomNames[NXAGENT_NUMBER_OF_ATOMS + 1] = +{ + "NX_IDENTITY", /* 0 */ + "WM_PROTOCOLS", /* 1 */ + "WM_DELETE_WINDOW", /* 2 */ + "WM_NX_READY", /* 3 */ + "MCOPGLOBALS", /* 4 */ + "NX_CUT_BUFFER_SERVER", /* 5 */ + "TARGETS", /* 6 */ + "TEXT", /* 7 */ + "NX_AGENT_SIGNATURE", /* 8 */ + "NXDARWIN", /* 9 */ + "CLIPBOARD", /* 10 */ + "TIMESTAMP", /* 11 */ + NULL, + NULL +}; + +static XErrorHandler previousErrorHandler = NULL; + +static void catchAndRedirect(Display* dpy, XErrorEvent* X) +{ + if (X -> error_code == BadAccess && + X -> request_code == X_ChangeWindowAttributes && + X -> resourceid == DefaultRootWindow(dpy)) + { + nxagentWMIsRunning = TRUE; + } + else + { + previousErrorHandler(dpy, X); + } +} + +static void startWMDetection() +{ + /* + * We are trying to detect if is there any client + * that is listening for 'WM' events on the root + * window. + */ + + nxagentWMIsRunning = FALSE; + + previousErrorHandler = XSetErrorHandler((XErrorHandler)&catchAndRedirect); + + /* + * After this request we need to Sync with + * the X server to be sure we get any error + * that is generated. + */ + + XSelectInput(nxagentDisplay, + RootWindow (nxagentDisplay, 0), + SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask); +} + +static void finishWMDetection(Bool verbose) +{ + XSetErrorHandler(previousErrorHandler); + + if (nxagentWMIsRunning) + { + if (verbose == 1) + { + fprintf(stderr, "Info: Detected window manager running.\n"); + } + } + else + { + if (verbose == 1) + { + fprintf(stderr, "Info: Not found a window manager running.\n"); + } + + /* + * We are not really interested on root window events. + */ + + XSelectInput(nxagentDisplay, RootWindow (nxagentDisplay, 0), 0); + } +} + +void nxagentWMDetect() +{ + Bool verbose = False; + int windowManagerWasRunning = nxagentWMIsRunning; + + startWMDetection(); + + XSync(nxagentDisplay, 0); + + if (windowManagerWasRunning != nxagentWMIsRunning) + { + verbose = False; + } + + finishWMDetection(verbose); +} + +int nxagentInitAtoms(WindowPtr pWin) +{ + Atom atom; + + /* + * Value of nxagentAtoms[8] is "NX_AGENT_SIGNATURE". + * + * We don't need to save the atom's value. It will + * be checked by other agents to find if they are + * run nested. + */ + + atom = MakeAtom(nxagentAtomNames[8], strlen(nxagentAtomNames[8]), 1); + + if (atom == None) + { + #ifdef PANIC + fprintf(stderr, "nxagentInitAtoms: PANIC! Could not create [%s] atom.\n", + nxagentAtomNames[8]); + #endif + + return -1; + } + + return 1; +} + +int nxagentQueryAtoms(ScreenPtr pScreen) +{ + int i; + static unsigned long atomGeneration = 1; + + int num_of_atoms = NXAGENT_NUMBER_OF_ATOMS; + char *names[NXAGENT_NUMBER_OF_ATOMS]; + + unsigned long int startingTime = GetTimeInMillis(); + + #ifdef TEST + fprintf(stderr, "nxagentQueryAtoms: Going to create the intern atoms on real display.\n"); + + fprintf(stderr, "nxagentQueryAtoms: Starting time is [%ld].\n", startingTime); + #endif + + nxagentPrintAtomMapInfo("nxagentQueryAtoms: Entering"); + + for (i = 0; i < num_of_atoms; i++) + { + names[i] = nxagentAtomNames[i]; + + nxagentAtoms[i] = None; + } + + if (nxagentSessionId[0]) + { + names[num_of_atoms - 1] = nxagentSessionId; + } + else + { + num_of_atoms--; + } + + startWMDetection(); + + nxagentInitAtomMap(names, num_of_atoms, nxagentAtoms); + + /* + * We need to be synchronized with the X server + * in order to detect the Window Manager, since + * after a reset the XInternAtom could be cached + * by Xlib. + */ + + if (atomGeneration != serverGeneration) + { + #ifdef WARNING + fprintf(stderr, "nxagentQueryAtoms: The nxagent has been reset with server %ld atom %ld.\n", + serverGeneration, atomGeneration); + + fprintf(stderr, "nxagentQueryAtoms: Forcing a sync to detect the window manager.\n"); + #endif + + atomGeneration = serverGeneration; + + XSync(nxagentDisplay, 0); + } + + finishWMDetection(False); + + /* + * Value of nxagentAtoms[9] is "NXDARWIN". + * + * We check if it was created by the NX client. + */ + + if (nxagentAtoms[9] > nxagentAtoms[0]) + { + nxagentAtoms[9] = None; + } + + /* + * Value of nxagentAtoms[8] is "NX_AGENT_SIGNATURE". + * + * This atom is created internally by the agent server at + * startup to let other agents determine if they are run + * nested. If agent is run nested, in fact, at the time it + * will create the NX_AGENT_SIGNATURE atom on the real X + * server it will find the existing atom with a value less + * than any NX_IDENTITY created but itself. + */ + + if (nxagentAtoms[8] > nxagentAtoms[0]) + { + nxagentAtoms[8] = None; + } + + if (nxagentAtoms[8] != None) + { + /* + * We are running nested in another agent + * server. + */ + + nxagentChangeOption(Nested, 1); + + /* + * Avoid the image degradation caused by + * multiple lossy encoding. + */ + + fprintf(stderr, "Warning: Disabling use of lossy encoding in nested mode.\n"); + + nxagentPackMethod = nxagentPackLossless; + } + + #ifdef TEST + + for (i = 0; i < num_of_atoms; i++) + { + fprintf(stderr, "nxagentQueryAtoms: Created intern atom [%s] with id [%ld].\n", + names[i], nxagentAtoms[i]); + } + + #endif + + nxagentChangeOption(DisplayLatency, GetTimeInMillis() - startingTime); + + #ifdef TEST + fprintf(stderr, "nxagentQueryAtoms: Ending time is [%ld] reference latency is [%d] Ms.\n", + GetTimeInMillis(), nxagentOption(DisplayLatency)); + #endif + + nxagentPrintAtomMapInfo("nxagentQueryAtoms: Exiting"); + + return 1; +} + +#define NXAGENT_ATOM_MAP_SIZE_INCREMENT 256 + +typedef struct { + Atom local; + Atom remote; + char *string; + int length; +} AtomMap; + +static AtomMap *privAtomMap = NULL; +static unsigned int privAtomMapSize = 0; +static unsigned int privLastAtom = 0; + +static void nxagentExpandCache(void); +static void nxagentWriteAtom(Atom, Atom, char*, Bool); +static AtomMap* nxagentFindAtomByRemoteValue(Atom); +static AtomMap* nxagentFindAtomByLocalValue(Atom); +static AtomMap* nxagentFindAtomByName(char*, unsigned); + +static void nxagentExpandCache(void) +{ + privAtomMapSize += NXAGENT_ATOM_MAP_SIZE_INCREMENT; + + privAtomMap = realloc(privAtomMap, privAtomMapSize * sizeof(AtomMap)); + + if (privAtomMap == NULL) + { + FatalError("nxagentExpandCache: realloc failed\n"); + } +} + +/* + * Check if there is space left on the map + * and manage the possible consequent allocation, + * then cache the atom-couple. + */ + +static void nxagentWriteAtom(Atom local, Atom remote, char *string, Bool duplicate) +{ + char *s; + + /* + * We could remove this string duplication if + * we know for sure that the server will not + * reset, since only at reset the dix layer + * free all the atom names. + */ + + if (duplicate) + { + s = strdup(string); + + #ifdef WARNING + if (s == NULL) + { + fprintf(stderr, "nxagentWriteAtom: Malloc failed.\n"); + } + #endif + } + else + { + s = string; + } + + if (privLastAtom == privAtomMapSize) + { + nxagentExpandCache(); + } + + privAtomMap[privLastAtom].local = local; + privAtomMap[privLastAtom].remote = remote; + privAtomMap[privLastAtom].string = s; + privAtomMap[privLastAtom].length = strlen(s); + + privLastAtom++; +} + +/* + * FIXME: We should clean up the atom map + * at nxagent reset, in order to cancel + * all the local atoms but still mantaining + * the Xserver values and the atom names. + */ + +void nxagentResetAtomMap() +{ + unsigned i; + + nxagentPrintAtomMapInfo("nxagentResetAtomMap: Entering"); + + for (i = 0; i < privLastAtom; i++) + { + privAtomMap[i].local = None; + } + + nxagentPrintAtomMapInfo("nxagentResetAtomMap: Exiting"); +} + +/* + * Init map. + * Initializing the atomNameList all in one. + */ + +static int nxagentInitAtomMap(char **atomNameList, int count, Atom *atomsRet) +{ + XlibAtom *atom_list; + char **name_list; + unsigned int i; + int ret_value = 0; + int list_size = count + privLastAtom; + + nxagentPrintAtomMapInfo("nxagentInitAtomMap: Entering"); + + atom_list = malloc((list_size) * sizeof(*atom_list)); + name_list = malloc((list_size) * sizeof(char*)); + + if ((atom_list == NULL) || (name_list == NULL)) + { + FatalError("nxagentInitAtomMap: malloc failed\n"); + } + + for (i = 0; i < count; i++) + { + name_list[i] = atomNameList[i]; + atom_list[i] = None; + } + + for (i = 0; i < privLastAtom; i++) + { + name_list[count + i] = privAtomMap[i].string; + atom_list[count + i] = None; + } + + /* + * Ask X-Server for ours Atoms + * ... if successfull cache them too. + */ + + ret_value = XInternAtoms(nxagentDisplay, name_list, list_size, False, atom_list); + + if (ret_value == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentInitAtomMap: WARNING! XInternAtoms request failed.\n"); + #endif + + free(atom_list); + free(name_list); + + return 0; + } + + for (i = 0; i < list_size; i++) + { + AtomMap *aMap = nxagentFindAtomByName(name_list[i], strlen(name_list[i])); + + if (aMap == NULL) + { + Atom local = MakeAtom(name_list[i], strlen(name_list[i]), True); + + if (ValidAtom(local)) + { + nxagentWriteAtom(local, atom_list[i], name_list[i], False); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentInitAtomMap: WARNING MakeAtom failed.\n"); + #endif + } + } + else + { + aMap -> remote = atom_list[i]; + + if (i < count && aMap -> local == None) + { + aMap -> local = MakeAtom(name_list[i], strlen(name_list[i]), True); + } + } + + if (i < count) + { + atomsRet[i] = atom_list[i]; + } + } + + free(atom_list); + free(name_list); + + nxagentPrintAtomMapInfo("nxagentInitAtomMap: Exiting"); + + return 1; +} + +/* + * If the nxagent has been resetted, + * the local value of the atoms stored + * in cache could have the value None, + * do not call this function with None. + */ + +static AtomMap* nxagentFindAtomByLocalValue(Atom local) +{ + unsigned i; + + if (!ValidAtom(local)) + { + return NULL; + } + + for (i = 0; i < privLastAtom; i++) + { + if (local == privAtomMap[i].local) + { + return (privAtomMap + i); + } + } + + return NULL; +} + +static AtomMap* nxagentFindAtomByRemoteValue(Atom remote) +{ + unsigned i; + + if (remote == None || remote == BAD_RESOURCE) + { + return NULL; + } + + for (i = 0; i < privLastAtom; i++) + { + if (remote == privAtomMap[i].remote) + { + return (privAtomMap + i); + } + } + + return NULL; +} + +static AtomMap* nxagentFindAtomByName(char *string, unsigned int length) +{ + unsigned i; + + for (i = 0; i < privLastAtom; i++) + { + if ((length == privAtomMap[i].length) && + (strcmp(string, privAtomMap[i].string) == 0)) + { + return (privAtomMap + i); + } + } + + return NULL; +} + +/* + * Convert local atom's name to X-server value. + * Reading them from map, if they have been already cached or + * really asking to X-server and caching them. + * FIXME: I don't really know if is better to allocate + * an automatic variable like ret_value and write it, instead of make all + * these return!, perhaps this way the code is a little bit easyer to read. + * I think this and the 2 .*Find.* are the only functions to look for performances. + */ + +Atom nxagentMakeAtom(char *string, unsigned int length, Bool Makeit) +{ + Atom local; + AtomMap *current; + + /* + * Surely MakeAtom is faster than + * our nxagentFindAtomByName. + */ + + local = MakeAtom(string, length, Makeit); + + if (!ValidAtom(local)) + { + return None; + } + + if (local <= XA_LAST_PREDEFINED) + { + return local; + } + + if ((current = nxagentFindAtomByLocalValue(local))) + { + /* + * Found cached by value. + */ + + return current->remote; + } + + if ((current = nxagentFindAtomByName(string, length))) + { + /* + * Found Cached by name. + * It means that nxagent has been resetted, + * but not the xserver so we still have cached its atoms. + */ + + current->local = local; + + return current->remote; + } + + /* + * We really have to ask Xserver for it. + */ + + { + Atom remote; + + remote = XInternAtom(nxagentDisplay, string, !Makeit); + + if (remote == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentMakeAtom: WARNING XInternAtom failed.\n"); + #endif + + return None; + } + + nxagentWriteAtom(local, remote, string, True); + + return remote; + } +} + +Atom nxagentLocalToRemoteAtom(Atom local) +{ + AtomMap *current; + char *string; + Atom remote; + + if (!ValidAtom(local)) + { + return None; + } + + if (local <= XA_LAST_PREDEFINED) + { + return local; + } + + if ((current = nxagentFindAtomByLocalValue(local))) + { + return current->remote; + } + + string = NameForAtom(local); + + remote = XInternAtom(nxagentDisplay, string, False); + + if (remote == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentLocalToRemoteAtom: WARNING XInternAtom failed.\n"); + #endif + + return None; + } + + nxagentWriteAtom(local, remote, string, True); + + return remote; +} + +Atom nxagentRemoteToLocalAtom(Atom remote) +{ + AtomMap *current; + char *string; + Atom local; + + if (remote == None || remote == BAD_RESOURCE) + { + return None; + } + + if (remote <= XA_LAST_PREDEFINED) + { + return remote; + } + + if ((current = nxagentFindAtomByRemoteValue(remote))) + { + if (!ValidAtom(current->local)) + { + local = MakeAtom(current->string, current->length, True); + + if (ValidAtom(local)) + { + current->local = local; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentRemoteToLocalAtom: WARNING MakeAtom failed.\n"); + #endif + + current->local = None; + } + } + + return current->local; + } + + if ((string = XGetAtomName(nxagentDisplay, remote))) + { + local = MakeAtom(string, strlen(string), True); + + if (!ValidAtom(local)) + { + #ifdef WARNING + fprintf(stderr, "nxagentRemoteToLocalAtom: WARNING MakeAtom failed.\n"); + #endif + + local = None; + } + + nxagentWriteAtom(local, remote, string, True); + + XFree(string); + + return local; + } + + #ifdef WARNING + fprintf(stderr, "nxagentRemoteToLocalAtom: WARNING failed to get name from remote atom.\n"); + #endif + + return None; +} + +#ifdef DEBUG + +static void nxagentPrintAtomMapInfo(char *message) +{ + unsigned i; + + fprintf(stderr, "--------------- Atom map in context [%s] ----------------------\n", message); + fprintf(stderr, "nxagentPrintAtomMapInfo: Map at [%p] size [%d] number of entry [%d] auto increment [%d].\n", + (void*) privAtomMap, privLastAtom, privAtomMapSize, NXAGENT_ATOM_MAP_SIZE_INCREMENT); + + for (i = 0; i < privLastAtom; i++) + { + fprintf(stderr, "[%5.1d] local: %6.1lu - remote: %6.1lu - [%p] %s\n", i, + privAtomMap[i].local, + privAtomMap[i].remote, + privAtomMap[i].string, validateString(privAtomMap[i].string)); + } + + fprintf(stderr, "---------------------------------------------\n"); +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h new file mode 100644 index 000000000..0dd75de43 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h @@ -0,0 +1,65 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Atoms_H__ +#define __Atoms_H__ + +#include "X.h" +#include "../../include/window.h" +#include "screenint.h" + +#define NXAGENT_NUMBER_OF_ATOMS 13 + +extern Atom nxagentAtoms[NXAGENT_NUMBER_OF_ATOMS]; + +extern Bool nxagentWMIsRunning; + +/* + * Create the required atoms internally + * to the agent server. + */ + +int nxagentInitAtoms(WindowPtr pWin); + +/* + * Query and create all the required atoms + * on the remote X server using a single + * round trip. + */ + +int nxagentQueryAtoms(ScreenPtr pScreen); + +/* + * Create the atoms on the remote X server + * and cache the couple local-remote atoms. + */ + +Atom nxagentMakeAtom(char *, unsigned, Bool); + +/* + * Converts local atoms in remote atoms and + * viceversa. + */ + +Atom nxagentRemoteToLocalAtom(Atom); +Atom nxagentLocalToRemoteAtom(Atom); + +void nxagentResetAtomMap(void); + +void nxagentWMDetect(void); + +#endif /* __Atoms_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Binder.c b/nx-X11/programs/Xserver/hw/nxagent/Binder.c new file mode 100644 index 000000000..cfea2cc77 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Binder.c @@ -0,0 +1,177 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include +#include +#include +#include + +#include "NX.h" + +#include "Binder.h" +#include "Options.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int nxagentCheckBinder(int argc, char *argv[], int i) +{ + if (++i < argc) + { + char *display; + char *found; + + int port; + + display = argv[i]; + + /* + * Check if a display specification follows + * the -B switch. + */ + + found = rindex(display, ':'); + + if (found == NULL || *(found + 1) == '\0' || + isdigit(*(found + 1)) == 0) + { + fprintf(stderr, "Error: Can't identify the display port in string '%s'.\n", + display); + + return 0; + } + + port = atoi(found + 1); + + #ifdef TEST + fprintf(stderr, "nxagentCheckBinder: Identified agent display port [%d].\n", + port); + #endif + + /* + * The NX options must be specified in the DISPLAY + * environment. Check if the display specified on + * the command line matches the NX virtual display. + */ + + display = getenv("DISPLAY"); + + if (display == NULL || *display == '\0') + { + fprintf(stderr, "Error: No DISPLAY environment found.\n"); + + return 0; + } + + found = rindex(display, ':'); + + if (found == NULL || *(found + 1) == '\0' || + isdigit(*(found + 1)) == 0 || atoi(found + 1) != port) + { + fprintf(stderr, "Error: The NX display doesn't match the agent display :%d.\n", + port); + + return 0; + } + + #ifdef TEST + fprintf(stderr, "nxagentCheckBinder: Identified NX display port [%d].\n", + atoi(found + 1)); + #endif + + /* + * Save the proxy options. They will be later + * used to create the transport. + */ + + nxagentChangeOption(Rootless, False); + nxagentChangeOption(Desktop, False); + nxagentChangeOption(Binder, True); + + /* + * FIXME: This now points to the buffer that was + * returned by getenv(). It is to be decided how + * to handle the values of type string in the + * Options repository. + */ + + nxagentChangeOption(BinderOptions, display); + + return 2; + } + + fprintf(stderr, "Error: No display port specified in command.\n"); + + return 0; +} + +int nxagentBinderLoop() +{ + struct timeval timeout; + + char *options = nxagentOption(BinderOptions); + + #ifdef TEST + fprintf(stderr, "nxagentBinderLoop: Creating the NX transport.\n"); + #endif + + if (NXTransCreate(NX_FD_ANY, NX_MODE_CLIENT, options) < 0) + { + #ifdef TEST + fprintf(stderr, "nxagentBinderLoop: PANIC! Error creating the NX transport.\n"); + #endif + + return -1; + } + + #ifdef TEST + fprintf(stderr, "nxagentBinderLoop: Yielding control to the NX entry point.\n"); + #endif + + while (NXTransRunning(NX_FD_ANY)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentBinderLoop: Going to run a new NX proxy loop.\n"); + #endif + + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + NXTransContinue(&timeout); + + #ifdef DEBUG + fprintf(stderr, "nxagentBinderLoop: Completed execution of the NX loop.\n"); + #endif + } + + #ifdef TEST + fprintf(stderr, "nxagentBinderLoop: Exiting the NX proxy binder loop.\n"); + #endif + + return 1; +} + +void nxagentBinderExit(int code) +{ + NXTransExit(code); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Binder.h b/nx-X11/programs/Xserver/hw/nxagent/Binder.h new file mode 100644 index 000000000..928db74fb --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Binder.h @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Binder_H__ +#define __Binder_H__ + +int nxagentCheckBinder(int argc, char *argv[], int i); + +int nxagentBinderLoop(void); + +void nxagentBinderExit(int code); + +#endif /* __Binder_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/CHANGELOG b/nx-X11/programs/Xserver/hw/nxagent/CHANGELOG new file mode 100644 index 000000000..1a63ce5b6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/CHANGELOG @@ -0,0 +1,5815 @@ +ChangeLog: + +nxagent-3.1.0-2 + +- Fixed TR11E01946. Forcing exposures on regions saved in the backing + store could bring to unexpected results. + +- Fixed TR11E01928. Animated cursors were not properly disconnected + and reconnected. + +nxagent-3.1.0-1 + +- Opened the 3.1.0 branch based on nxagent-3.0.0-93. + +nxagent-3.0.0-93 + +- Fixed TR10E01913. Now bell settings are restored after the agent + reconnects. + +nxagent-3.0.0-92 + +- Fixed a compilation error on 64 bit platforms. + +nxagent-3.0.0-91 + +- Checked the window synchronization status before subtracting an ex- + posed area from the corrupted region. + +nxagent-3.0.0-90 + +- Fixed TR11E01932. In case of rootless session displayed by NXWin X + server, synthetic ConfigureNotify events are generated by the X11 + agent. This helps to correct menu navigation in Java 1.6.0. + +- Fixed the handling of 'client' parameter. + +- Fixed bad refreshes in viewport navigation in the case of Windows + client. + +- Fixed TR11E01930. If the defer level is set by means of the command + line, the DeferLevel option is not reset while resuming the session. + +- Fixed string comparison in the font replacement routine. + +- Printed the new geometry in the session log when the agent screen is + resized. + +nxagent-3.0.0-89 + +- Fixed TR10E01919. The agent could crash in the routine in charge of + find a replacement for a missing font. + +- Removed an unuseful log message. + +nxagent-3.0.0-88 + +- Fixed TR10D01539. Some XKEYBOARD requests are disabled if the option + 'keyboard' has value 'query'. This locks the initial keyboard map. + Enabling/disabling of XKEYBOARD requests is done at run time. + +- Added -noxkblock command line option enabling the XKEYBOARD requests + even if the option 'keyboard' value is 'query'. + +nxagent-3.0.0-87 + +- Reworked the handling of CT_PIXMAP client clips. Clips are always + converted in regions for internal use, while bitmap are saved for + operations involving the remote X. + +nxagent-3.0.0-86 + +- Fixed TR07E01749. Now using different resolution between shadow + and master session with shadow display option 'As on the server' + doesn't display black borders. + +- Fixed TR09E01852. The GC clips of type CT_PIXMAP are not converted + in regions. This avoids generating regions made up by thousands of + rectangles. Backing store function SetClipmaskRgn is implemented by + a stub doing nothing. + +nxagent-3.0.0-85 + +- Fixed TR08E01841. Exposed are forced to new areas exposed by the + viewport. + +- Fixed TR02E01645. Remote exposures was blocked if the NX client was + running on Linux without window manager. + +- Even if the agent window is fully obscured, synchronization is not + skipped if the Composite extension of the remote display is in use. + +- Fixed TR08E01851. Exposures events have to be internally generated + for regions that can't be restored because the backing pixmap is + corrupted. + +- Fixed TR08E01847. The initial values of store used to save XChangeGC + calls are set to the default GC values. + +- When a drawable becomes synchronized, its outdated bitmap is destro- + yed. + +- If a pixmap is not fully synchronized after a synchronization loop + it is cleared, just like windows. + +- Solved a problem causing some pixmaps to remain among the corrup- + ted resources even if they were synchronized. + +nxagent-3.0.0-84 + +- Renamed Misc.h as Utils.h to solve name clashes on Windows platform. + +nxagent-3.0.0-83 + +- Changes to include correctly declaration of _XDisplay structure on + 64 bit platforms. Further tests are needed to confirm that it fixes + TR08E01824. + +nxagent-3.0.0-82 + +- Fixed TR08E01821. Changed nxagentAddItemBSPixmapList() to check if + the pixmap item has already an entry in the list before adding it. + +- Fixed TR07E01795. Sun Studio main window showed only its grey back- + ground. Changed clipboard events handling to let the agent notify + a failure in converting selection. + +nxagent-3.0.0-81 + +- Based on nxagent-3.0.0-78. + +- The agent options are saved before reopening the display in the + reconnection procedure. If the new initialization fails the backup + values of options are restored. + +- Keyboard device info are saved before the keyboard reset occuring + in the reconnection procedure. If the new initialization of the + keyboard fails, the old values are restored. + +- The initialization procedure of keyboard device returns with error + if it fails to retrieve the keyboard mapping information from the + remote display. + +- The reconnection fails if the default depth of the new display is + different from the previous one. + +- The session can be migrated if the visuals don't match for color + masks swapping. At the moment there are no conversions to line up + the RGB masks, so even if the session can be migrated, incorrect + colors may be shown. + +nxagent-3.0.0-80 + +- The agent options are saved before reopening the display in the + reconnection procedure. If the new initialization fails the backup + values of options are restored. + +- The flag storing that a SIGHUP has been received is reset if the + function reconnecting the session fails. + +nxagent-3.0.0-79 + +- Changed the SIGHUP handler not to ignore the signal if the state + is SESSION_GOING_UP or SESSION_GOING_DOWN. + +- Keyboard device info are saved before the keybord reset occuring + in the reconnection procedure. If the new initialization of the + keyboard fails, the old values are restored. + +- The initialization procedure of keyboard device returns with error + if it fails to retrieve the keyboard mapping information from the + remote display. + +- The reconnection fails if the default depth of the new display is + different from the previous one. + +- The session can be migrated if the visuals don't match for color + masks swapping. At the moment there are no conversions to line up + the RGB masks, so even if the session can be migrated, incorrect + colors may be shown. + +nxagent-3.0.0-78 + +- Fixed TR07E01747. Fixed warnings occuring when compiling for AMD64. + +- Fixed TR07E01753. NoMachine WM icon in the title bar is displayed + correctly. + +- Fixed TR03E01656. If client and server endianess didn't match, glyph + images bits have to be only temporarily swapped. + +- Fixed TR07E01746. Terminate the shadow agent if the option 'shadow' + is empty. + +- Added option '-verbose'. It enables the printing of errors received + by the agent from the remote X server. + +- Warnings related to missing fonts are printed only if verbose mode + is enabled. + +- Disabled a log message related to the use of Composite extension. + +nxagent-3.0.0-77 + +- The pixmap formats are initialized without taking care of which are + supported on the remote display. + +- Removed the check for pixmap format compatibility when migrating the + session to a new display. + +- Fixed TR06E01725. A minimum set of available picture formats is + used to ensure a wide migration from/to different displays. + +- The PictFormat structures used by nxagent are no longer filtered + with the ones available on the real display. + +- The background pixmaps are cleared while reconnecting in order to + make them usable. + +- Fixed TR01E01619. Changed the RandR implementation to return a re- + fresh rate other than zero. + +nxagent-3.0.0-76 + +- Changed the keystroke to force the drawable's synchronization to + CTRL-ALT-J. + +nxagent-3.0.0-75 + +- If the backing store tries to restore areas from a corrupted pixmap, + such areas are subtracted from the saved region, so that exposures + will be sent for them. + +nxagent-3.0.0-74 + +- Don't skip the synchronization when there are more clients ready. + This temporarily solves the synchronization problems observed in + the previous versions if one or more clients kept the agent busy. + +nxagent-3.0.0-73 + +- If the PolyFillRect() uses a FillStippled or a FillOpaqueStippled + fill style and the destination is corrupted, the area affected by + the operation is first synchronized. + +nxagent-3.0.0-72 + +- Fixed the bug affecting the position of the input window when a + session was migrated to a linux X server with no window manager + running. + +- The color used to fill the corrupted backgrounds is converted de- + pending on the depth of remote X server. + +- The PolyFillRect() does not clean the corrupted destination region + if a stipple pixmap is used as mask. This solution is adopted to + reduce the region fragmentation and to solve the text drawing pro- + blems affecting rdesktop. + +nxagent-3.0.0-71 + +- Force a flush of the display buffer if the coalescence timeout is + expired. Set the timeout according to the link type, from 0 to 50 + ms for link MODEM. + +- In nxagentRealizeImage() the width in byte is computed newly if + the image has been scaled. + +- The shadow agent clips the screen updates in tile only if the link + type is MODEM or ISDN. + +- Split the abort conditions in the synchronization loop to check + separately the congestion and the blocking status. + +- Implemented a workaround in order to avoid graphical problems with + render composite operations on Xfree86 remote server. + +nxagent-3.0.0-70 + +- Various adjustments aimed at using the best defer rules depending + on the congestion state. + +- Fixed a problem with icons of message boxes in shadow sessions. + +- Changed the log message printed when the shadow agent can't connect + to the master session. + +- If Composite is in use, don't skip the PutImage and CopyArea opera- + tions even if the agent window is fully obscured. + +nxagent-3.0.0-69 + +- The option -nodamage prevents the shadow agent from using the damage + extension. + +- Changed the scaling feature to set the byte order of the source + image according to the local endianess. + +- Changed the scaling feature in order to handle different ratios for + horizontal and vertical sizes. + +- Force the shadow sessions to be non-persistent. + +- When a pixmap background is synchronized, an expose is sent to its + owners. + +nxagent-3.0.0-68 + +- Changed the type of parameters passed to nxagentRootlessRestack in + order to be compliant with Xlib types on 64 bit platfors. + +- The nxagentCompositeRects() checks for the render operation type to + determine if the corrupted destination region must be cleared. + +nxagent-3.0.0-67 + +- Fixed a condition discarding the expose events received from the X + server. + +nxagent-3.0.0-66 + +- The corrupted resources are removed when a session suspends, and are + reallocated only at reconnection. This is aimed at avoiding synchro- + nization loops when the link is down. + +nxagent-3.0.0-65 + +- Initialize for now the tile size at 64x64 in shadow mode. + +- The height and width of the tiles used for synchronizing drawables + are set without overriding command line option 'tile'. + +- Avoid calling miWindowExposures() for empty regions. + +- Fixed a bug while clearing corrupted regions with window exposures. + +- The corrupted drawable counters are not reset if there are bitmaps + to synchronize. + +nxagent-3.0.0-64 + +- The synchronization bitmap is used only when requesting a full + drawable synchronization, otherwise the frame-buffer is used as + source. + +- Fixed some bugs in the synchronization loop. + +- Removed the remaining debug output. + +nxagent-3.0.0-63 + +- Don't start the synchronization loop if the wakeup handler found + some clients ready. + +- Don't flush the display buffers if the synchronization was inter- + rupted and there are more drawables to synchronize. + +- Changed the backing store functions to not save the obscured areas + which are inside the corrupted region of a window. + +- Added the code to send the XClearArea() commands in shadow mode at + the end of the synchronization loop. In this way large images are + still split in tiles but, on fast links, the final result can made + visible all at once. + +- Modified the corrupted drawable counters to only report the number + of resources needing synchronization. This allows the block hand- + ler to avoid spinning through the synchronization loop if there is + nothing to do. + +- On a window exposure remove the corrupted region of the destinat- + ion window. + +- For testing purposes, the pixmap synchronization loop starts only + if there are corrupted backgrounds. + +nxagent-3.0.0-62 + +- The image scaling is applied only if the destination drawable is the + pixmap shadowing the frame buffer of the master session. + +- The shadow agent exits with a fatal error if it can't connect to the + master session. + +nxagent-3.0.0-61 + +- Forward the SIGCHLD to the NX transport instead of letting the NX + transport forward the signal to us. This allows the agent to set + and replace the signal handler at any time, without having to ta- + ke care of the state of the NX transport. + +- Improved the synchronization loop by implementing a simple round- + robin mechanism between the resources needing synchronization. + +nxagent-3.0.0-60 + +- Use a new set of functions to install, post-install and reset the + signal handlers. + +- Reset the signal handlers to their initial state after a display + failure, as part of the disconnection procedure. + +- Don't set SA_RESTART in the sigaction flags. Make the signal int- + errupt the system call. + +- Terminate all the running dialogs before exiting. + +nxagent-3.0.0-59 + +- Use the value of nxagentCongestion in nxagentUserInput() instead + of calling NXDisplayCongestion(). + +nxagent-3.0.0-58 + +- The clip mask of the scratch GC used by nxagentDeferCopyArea() is + reset before releasing the GC. + +- The MotionNotify event can now break the synchronization loop. + +- In the case of shadow sessions, if synchronization aborts then the + remaining data to synchronize are not stored in a bitmap. + +- If a table rebuild occurs in a loop searching for resources, the + loop restarts from beginning not to use the out of date table. + +nxagent-3.0.0-57 + +- The synchronization bitmap is created only if the corrupted area + of the source drawable is visible. + +- The synchronization loop skips the last synchronizing drawable to + give a chance to the next resources to be synchronized. + +- Removed the session starting infos concerning the mismatching ver- + sions of render and the window manager detection. + +- Split the gliph lists in Render.c only if the symbol SPLIT_GLYPH_- + LISTS is defined. + +- Read again the events in the block handler after the flush. + +- The nxagentCongestion variable is now a value ranging from 0 to 9, + not a boolean flag. + +- Added some experimental code dynamically reducing the size of the + display output buffer when the agent is blocking for write. + +nxagent-3.0.0-56 + +- The synchronization loop is now aborted when a short timeout exp- + ires. If the drawable synchronization cannot be completed, the + remaining data is stored in a bitmap. The synchronization loop is + then restarted using the data from the bitmap, instead of pulling + the latest image from the framebuffer. This allows the agent to + show a complete frame when displaying videos and animations, while + at the same time giving a chance to the clients to update the + screen in background. When an image from the saved bitmap is put + on the remote display, the image is compared with the actual data + in the framebuffer. If the two bitmaps match, the corresponding + region of the drawable is marked as synchronized, otherwise the + drawable remains dirty and will be synchronized at the next loop + using the new data taken from the framebuffer. + +- If the smart schedules is enabled, let the dispatcher decide when + it is time to yield and process the next client. + +nxagent-3.0.0-55 + +- Disable the smart scheduler in the case of shadow sessions. + +- If the smart scheduler is enabled, stop the timer before returning + from the block handler. WaitForSomething() sets a zero timeout if + there are clients with input but doesn't stop the timer. The select + is then interrupted to update the schedule time even if, what the + dispatcher cares, is only the ticks count at the time the client + is scheduled in. + +- Fixed a compilation warning in NXresource.c. + +- The main window of the shadow agent is mapped in nxagentMapDefault- + Windows, like for non shadow agents, if the remote display has no + window manager running. This avoids a flickering effect on the !M + logo having place if the shadow session was displayed from a Wind- + ows client. + +- Some code related to the use of the Composite extension is not built + in the agent being not necessary anymore. + +nxagent-3.0.0-54 + +- Get SmartScheduleStopTimer() from dixstruct.h. + +- Updated the NoMachine icon file. + +nxagent-3.0.0-53 + +- Changed the message 'NXAGENT: Fatal IO error on display' into 'Info: + Disconnected from display'. + +- Fix a problem occurring when the FindClientResourcesByType() needs + to reallocate the resource table. + +- The popup window synchronization breaks if an user input is caught. + +- Implemented FR05E01712. The stderr and stdin are redirected to the + 'clients' file in the session directory. + +- The nxagentRealizeImage function does nothing if the agent is not + connected to the display. + +- Removed the code implementing the redraws of the viewport frame. + Such code is not needed because is't enough for the agent to handle + the expose event received from the X server. + +nxagent-3.0.0-52 + +- Where it is necessary to wrap the function PaintWindowBackground, + the original function pointer is saved and restored afterwards. This + let other code wrapping that function (e.g. the damage extension) to + work correctly. + +- If the agent works in shadow mode, the defer parameters are ignored. + +nxagent-3.0.0-51 + +- Use the smart scheduler on platforms where it is enabled. + +- Check ClientsWithInput in the wakeup handler and update the number + of clients ready if any descriptor is set. + +nxagent-3.0.0-50 + +- Fixed TR05E01714. Changed VisibilityNotify event so that it forces + a refresh on the root window, but only if on the agent Composite is + enabled and its window moves from a VisibilityFullyObscured to ano- + ther state. + +- Grant the availability of core fonts in master sessions also after + the disconnection. This makes possible to start new clients inside + a shadow sessions while the master is down. + +- Changed nxagentGlyphs() to send a single glyph list per request. + +- Major rewrite of the agent dispatch handler. + +- Some name changes to the functions handling the session states. + +nxagent-3.0.0-49 + +- Made the dispatch loop yield control to a different client after a + fair amount of time even if the current client doesn't produce any + output. + +nxagent-3.0.0-48 + +- Modified the message in the suspend dialog to say 'Disconnect' in + place of 'Suspend'. + +- Added macros in Pixels.h to determine the behavior of the lazy en- + coding. + +- Changed the copyright attribution from Medialogic to NoMachine. + +- Reset all options to their defaults before processing the session + arguments. This fixes the problem with the DeferLevel option not + being set at reconnection. + +nxagent-3.0.0-47 + +- Initialized the arguments of NXGetControlParameters(), NXGetShmem- + Parameters() and NXGetUnpackParameters() to end up with valid data + also in the case of a display failure. + +- Converted the coordinates in the X_PolyFill requests to relative + mode. This makes all the requests independent from the origin and + helps the caching by the proxy. + +nxagent-3.0.0-46 + +- Don't print the 'Display failure' message on a SIGTERM. + +- Ensure that the NX transport is shut down after the 'Terminating + session at...' message if the session is killed by the user. + +- Let the agent filter the error output by setting the OsVendorVEr- + rorFProc function pointer. + +- Give the possibility to the agent to redirect the standard error + during a Popen() or a System() by setting the OsVendorStartRedir- + ectErrorFProc and OsVendorEndRedirectErrorFProc function pointers. + +- Fixed a problem in nxagentPolyFillRect() not properly propagating + to the destination. + +- Added nxagentPolyFillRect() and nxagentGlyphs() among the funct- + ions increasing the pixmaps usage counter. + +- Cleaned up some of the FIXME related to the lazy encoding. + +nxagent-3.0.0-45 + +- Use the three distinct functions in nxcompext to query the state + of the display connection. + +- Terminate gracefully on a fatal server error by printing the fol- + lowing in the session log: + + Error: Aborting session with 'Error text...'. + Session: Aborting session at '...'. + Session: Session aborted at '...'. + +- Removed more debug messages from the session log. + +nxagent-3.0.0-44 + +- Guess whether to compress an image with a lossless encoder based + also on the width and height, not only on size. + +- Corrupted pixmaps used as tiles propagate the dirty area when they + are involved in a PolyFillRect() operation. + +- On link settings ADSL to LAN, images are not split in tiles to bet- + ter fill all the available bandwidth. + +- Pixmaps referenced often as source in deferred operations or used + as backgrounds, are now synchronized as long as when the network + congestion level remains 0. + +- Use nxagentPaintWindowBorder() to update the window's border in + the framebuffer. + +- Fixed a problem with the new handling of the X_RenderChangePicture + requests that caused the text to be erroneously clipped. + +nxagent-3.0.0-43 + +- Don't pass the uid of the shared memory segment to the nxcompshad + library if it can't be retrieved from the options. + +- Fixed the new handling of the RenderChangePicture requests to work + on 64 bit platforms. + +nxagent-3.0.0-42 + +- Added support for the 'lossy', 'lossless' and 'adaptive' pack me- + thod literals. These values activate the dynamic selection of the + pack method by the agent. + +- Use the newer constant PACK_NONE instead of NO_PACK. + +nxagent-3.0.0-41 + +- Fixed a bug in the disconnection procedure introduced with the new + handling of the display events. + +- Realize the XRenderChangePicture() request only if a change of the + remote picture's attributes is detected. + +nxagent-3.0.0-40 + +- Dynamically select a lossy or a lossless encoder based on the num- + ber of pixels that appear to be different in the image. + +- Use the new PACK_BITMAP_16M_COLORS image encoding. Handle the case + when the packed image data points at the same data as the original + image. This is useful to save a copy. + +- The PACK_BITMAP_16M_COLORS method is now the default for lossless + encoding. + +- Don't use compression for the alpha channel. This is also intended + to better leverage the stream compression. + +nxagent-3.0.0-39 + +- The nxagentComposite() function doesn't check the source and mask + synchronization status, but defers the XRenderComposite() operation + by checking the defer level only. + +- If the target of an XCompositeText() function is an hidden window, + the operation is prevented. + +- Passing the uid of master X server process to nxcompshad library. + +- Before the call of XRenderAddGlyphs(), call the new library function + XRenderCleanGlyphs() cleaning the padding bytes of data section of + request. + +nxagent-3.0.0-38 + +- Don't warp the cursor if the requesting client is a shadow agent. + +- Changed a call to NXFlushDisplay in order to align to nxcomp version + 3.0.0-15. + +- Updated the NoMachine icon file. + +- Changed Agent.h in order to include NX version of Xlib.h avoiding + missing declarations. + +- If the NXDisplayCongestion notifies an optimum congestion state, + the continuous user input, due to unreleased buttons/keys, doesn't + break the drawable's synchronization. + +- Renamed the option 'block' as 'tile'. + +- Implemented a way to guess if the destination drawable of a copy + area is a popup window. In such a case, the source is synchronized + before doing the copy to avoid ugly effects like text items floating + on an invisible background. + +- In order to reduce the number of clip mask changings, if the clean + region of a corrupted source drawable is formed by a single rectan- + gle, its coordinates are used to change extents and position of the + area involved in the copy area operation. + +- Fixed a crash caused by a reference to a resource table freed by a + table rebuilding. This was happening because during the pixmap re- + connection some new GC resources went beyond the resource table li- + mit, causing a table relocation. As a general rule, a function loop- + ing across a resource table should not add or remove resources. + +nxagent-3.0.0-37 + +- To improve the efficiency of the algorithm deferring the trapezoid + operations, the composite does not propagate the glyphs flag to + the destination. + +- Moved the replacement of XCheckIfEvent() to nx-X11 with the name + XCheckIfEventNoFlush(). + +nxagent-3.0.0-36 + +- Changed nxagentDisplayFlushHandler() according to the new semantic + of the handler. The function is called by nxcomp when new data is + sent to the remote proxy. + +- After the flush handler is called, use NXQueryDisplay() with query + type NXDisplayCongestion to update the congestion flag. + +- Modified the boxes list defragmentation to merge only those rectan- + gles which fully overlap. + +- During the synchronization loop the nxagentDispatchHandler() takes + care of reading the enqueued events, while the nxagentUserInput() + checks only for state changes due to a processed key/button event. + +- Set the display output buffer size according to the link type. + +- Removed the congestion and synchronization callbacks. + +nxagent-3.0.0-35 + +- In order to avoid the lossy encoding of text regions, the nxagent- + GlyphsExtents is computed even if the mask format is not specified. + In this case, the render implementation was not calculating the ex- + tents of composite text operation, whose coordinates are useful only + to build a mask pixmap. + +nxagent-3.0.0-34 + +- Removed message 'Could not init font path element' from the output. + +- Moved initialization of picture support before the call to miDCInit- + ialize in the screen opening procedure. This is because miDCInitial- + ize calls DamageSetup that wraps the picture screen functions. + +- Implemented FR05E01686. Added option 'menu' enabling/disabling the + pulldown menu in the rootless agent. + +- Added a flag to each drawable to record if they have been the dest- + ination of a glyph operation. This is used to skip the deferral of + some operations (e.g. render trapezoids) if they can cause the + drawable to be synchronized using a lossy encoding. + +- The render trapezoids are deferred if the operation falls inside + a dirty region or if the destination drawable does not contain + glyphs. + +- Imported the NXmitrap.c file from render directory. + +- Improved the algorithm queuing multiple writes across a proxy + flush. + +nxagent-3.0.0-33 + +- Read the event queue after each request processed. Doing this + is expensive but it seems to work best. + +- Don't split the big trapezoid requests. Splitting the requests + doesn't seem to provide any benefit with the clients tested. + +- By defining BLOCKS in Handlers.c, Events.c and NXdispatch.c, log + the begin and end of the most sensitive routines. + +nxagent-3.0.0-32 + +- Use NXSetDisplayWriteHandler() to register a callback invoked + by Xlib after some data is written to the display socket. This + callback allows the agent to better determine when it is time + to send the sync requests. + +nxagent-3.0.0-31 + +- The operation of adding glyphs to remote glyphset has been defer- + red, in order to avoid to add unused glyphs. When a composite text + operation looks for a certain glyph, if it has not been added to + the selected glyphset, an XRenderAddglyphs is requested. + +- The forced synchronization timeout is now dependant on link type. + +- Force the mi to process the events just after having processed + any input. + +- Added an experimental 'hard' sync request intended to wait for + the X server to complete an image operation. This also affects + the agent only when the NX transport is not running. + +- Added a synchronization mechanism intended to let the agent de- + tect if the X server is not able to process its input when the + NX transport is not activated. The algorithm uses asynchronous + X_GetInputFocus replies to minimize the impact of latency on + slow connections. A new request is sent at any given amount of + bytes read from our clients. When the number of pending replies + is exceeded, the agent stops accepting additional requests and + waits for the remote until the number of pending replies returns + below the limit. Note that when the NX transport is running, the + algorithm is disabled to not interfere with the proxy's own + token-based flow control. + +- Added the nxagentDispatchHandler() function. It is called by the + dispatcher after a client's request has been processed. + +- Added the nxagentWaitEvents() function. It blocks waiting for + more input with an optional timeout. It handles the case when + the NX transport is not running and is able to recover gracely + from a display failure by returning the error. + +- Replaced most of the code that was relying on NXTransContinue() + to use the new function. + +- Moved the new event-related functions to Events.h and Events.c. + +- Disabled the code raising the splash screen at reconnection. + +- Reverted change done in 3.0.0-8 version, dealing with expose events + not having entries in the queue. They are not collected in a global + region but sent immediately. + +nxagent-3.0.0-30 + +- Let the block handler check if there are events queued after the + flush before entering the select. + +- Changed the dispatch loop to read the incoming events more often. + +- Added the nxagentReadEvents() and nxagentCheckEvents() functions. + Differently from XCheckIfEvent(), nxagentCheckEvents() doesn't + flush the output buffer if no event is available. nxagentReadEv- + ents(), instead, it's like XEventsQueued() but forces the use of + the QueuedAfterReading mode. These functions should be used when- + ever XEventsQueued() and XCheckIfEvent() would be required. + +- The nxagentQueuedEvents() macro uses XQLength() to return the + number of events that have been read and need to be dispatched. + +- The nxagentPendingEvents() function returns true if there is any + event queued. If not, it queries the transport to find if more + events can be read. + +- Ripristinated the code preventing the agent to connect to its own + display. The code was disabled while migrating to the new tree. + +- Removed the dependencies from the NXAGENT_QUERYBSIZE, NXAGENT_NO- + EXPOSEOPTIMIZE and NXAGENT_ONEXIT. Removed the unused code. + +- Removed more unused code in Clipboard.c. + +- The shadow agent calls NXShadowDestroy before exiting. + +- Reverted a change done in 3.0.0-8 dealing with expose events. If the + result of the subtraction is not sent immediately, some duplicated + refresh is shown. + +nxagent-3.0.0-29 + +- The splash screen is removed as soon as the session is started in + the case of shadow session. + +- The rules to verify when the synchronization loop can be stopped + are specified by means of a bitmask passed as parameter to synch- + ronization functions. + +- The glyphsets are no longer reconnected during a session resuming, + but only when they are used. + +- Initialized the timeout parameter in block handlers in case of NULL + value. + +- Added option 'block' to specify the size of image slices sent during + the synchronization. + +- Fixed a memory leak in nxagentParseOptions(). + +nxagent-3.0.0-28 + +- Improved the nxagentGetOptimizedRegionBoxes() function to optimize + the high fragmented rectangle lists. + +- When resizing nxagent window the fictitious resize for all top level + windows, triggering the window tree validation, is not executed if + rootless mode is off. + +- The nxagentInputWindows cannot be resized in rootless mode because + they are not created. + +- Added NXdamage.c to the source files. + +- Changed damage's GCOps functions drawing text. This was needed be- + cause the original functions didn't call agent GCOps if the drawable + was registered for damage events. + +nxagent-3.0.0-27 + +- Fixed TR04E01677. Changed the reconnection procedure to call the + function destroying the NoMachine splash window. It rarely happened + that the splash window was not removed after resuming a session. + +- Ignored the ForceScreenSaver requested by X clients to avoid clashes + with our screen saver handling. + +- Cleanup of code handling the screen saver timeout to remove referen- + ces to the old drawable's synchronization method. + +- Fixed TR04E01664. The session is terminated instead of suspended if + the auto-disconnect timeout expires and the persistence is not allo- + wed. + +- Reverted an optimization in nxagentCheckWindowConfiguration() in + order to avoid inconsistencies in the stacking order. + +- Fixed a segmentation fault in rootless mode. + +nxagent-3.0.0-26 + +- Some fixes to build in the Cygwin environment. + +nxagent-3.0.0-25 + +- Renamed the option 'lazylevel' to 'defer'. + +- Added a flag to windows to know if they have transparent children, + in order to reduce to minimum the put images on windows covered by + their children. + +- Created a generic list of graphic contexts, used when synchronizing + drawables between the nxagent and the remote X server. All the GCs + are created with IncludeInferiors property. This solves problem when + trying to synchronize windows covered by children with transparent + backgrounds. + +- The nxagentUserInput checks if keys are pressed. + +- Fixed some memory leaks. + +- In shadow mode, removed the handling of events of the source display + from the code. They can be handled in the nxcompshad library. + +- In shadow mode, allow the synchronization loop to break in case of + input event. + +- Moved the call to miDCInitialize after the initialization of poin- + ters to screen functions. This was needed to make DAMAGE work pro- + perly. + +- In shadow mode, not breaking the polling if a mouse button is down. + +- In shadow mode, allow events to break the loop sending updates. + +- At reconnection the input window is raised after the root window is + mapped. + +- Fixed an invalid read. The call to the function nxagentSetInstalled- + ColormapWindows() has been moved from nxagentDestroyWindow to Dele- + teWindow. + +nxagent-3.0.0-24 + +- The corrupted drawables are added to dedicated lists of resources + to speed up the synchronization process. + +- The nxagentUserInput checks if a mouse button is pressed. + +- Created the nxagentGetScratchGC which resets the scratch GCs to de- + faults values also on the remote X server. + +- The synchronization cycle is forced when a timeout expires, albeit + the remote display is blocked. + +- Added a parameter to synchronization functions to specify if loops + can break. It's useful to force the synchronization in some circum- + stances. + +- Keystroke CTRL-ALT-R is enabled in shadow mode too. It is used to + switch scaled and non-scaled modes. + +- Some changes to adjust the window position. + +- Moved some macros to Misc.h. + +- Some changes to adjust the behaviour of scaling feature in case of + resize and switch to full screen. + +- Freeing the buffer used for scaling if no needed anymore. + +nxagent-3.0.0-23 + +- Fixed TR02E01648 and TR10D01534. Changed pointer motion events han- + dling. In desktop mode the nxagent creates a InputOnly window that + collects the MotionNotify events. This window is mapped over the + root window. In rootless mode the nxagent creates all windows on + real X server with PointerMotionMask. + +- Not exiting from the block handler with zero timeout if drawables to + be synchronized are pixmaps only. + +- Reduced the margin around the glyph extent from 5 to 3 pixels. + +nxagent-3.0.0-22 + +- Fixed initialization of XImage used for scaling. + +- Changes to fix the position of the shadow main window. + +nxagent-3.0.0-21 + +- Moved the implementation of scaling feature in nxagentRealizeImage. + +- Disabled log message 'Font not found' in Font.c. + +- The synchronization loop is called inside the BlockHandler. Synch- + ronization goes on until the display is not blocked. + +- Exiting the BlockHandler with timeout zero if corrupted drawables + have not been synchronized because of blocked display connection. + +- Changed the synchronization loop to slice the dirty regions. + +- The updates by shadowing nxagents are now sent using the lazy me- + chanics: the remote buffer pixmap is marked as dirty, then synch- + ronized. + +- Traversing the tree to synchonize windows. + +nxagent-3.0.0-20 + +- Fixed a bug in the nxagentGetOptimizedRegionBoxes() function which + was causing a bad merging of boxes. + +- Added a margin of 5 pixels around the glyphs extents before synch- + ronizing them. + +- The synchronization cycle has been reactivated for the first lazy + level, in order to synchronize the window's background. + +- The CopyArea between pixmaps doesn't mark the full destination as + corrupted, but clips the operation with the synchronized area of the + source as happens for the windows. + +- Implemented scaling feature for the shadow agent. To do: run-time + control of this feature by keystrokes and window resize; adapting + the window size to the scaled dimensions. + +- Setting the shadow session scaling ratio equal to the size chosen + from the user divided by the size of the main session. + +- Scaled mouse motion events according with the ratio. + +- Implemented the nxagentScaleImage() function. + +- Updated version number and copyright in the output log. + +- Fixed TR06D01390. When resizing nxagent window, we make a fictitious + resize for all top level windows, in order to trigger the window + tree validation. + +nxagent-3.0.0-19 + +- Force LazyLevel to 0 in case of shadowing session. + +- If shadowing poller returns that nothing is changed and no updates + have to be sent, call WaitForSomething select with 50 ms timeout. + +- The shadow agent doesn't break the sending of updates in case of + mouse motion events. + +- The scratch GC's clip mask was not cleared during a drawable synch- + ronization. Now the GetScratchGC() function is called after changing + the nxagentGCTrap flag. + +- Implemented the function nxagentGetOptimizedRegionBoxes(). It gets + the list of boxes forming a region and operates on it to merge as + much boxes as possible, checking their width and position. + +- Implemented the function nxagentClearRegion(). It does an XClearA- + rea() for each box belonging to a region, using the color returned + by nxagentGetCorruptedRegionColor() as background of target window. + +- Implemented the function nxagentGetCorruptedRegionColor(). It gets + the color of first outer pixel in the bottom right corner of re- + gion. + +- Fixed some memory leaks. + +- Checked and removed some FIXME concerning the lazy encoding. + +- Fixed and added some debug messages in Render.c, GC.c and GCOps.c. + +- Added to the Literals.h file the Render and Shared memory requests. + +nxagent-3.0.0-18 + +- Changes to comply with nxcompshad library. + +nxagent-3.0.0-17 + +- The master agent holds the number of shadow nxagents connected to + itself. The shadow nxagent notify its presence to master nxagent + by setting the _NX_SHADOW property. + +nxagent-3.0.0-16 + +- Rearranged the lazy level rules. All the link types now use the lazy + level 1: the pixmaps are always corrupted, and they becomes synchro- + nized only when they're sources of an operation (i.e. CopyArea, ren- + der). + +- The lazy levels greater than 1 don't synchronize automatically. It's + possible to synchronize with two keystrokes: CTRL+ALT+Z forces the + windows synchronization without take care of the congestion; CTRL+ + ALT+X synchronizes the windows and the background until there is + enough bandwidth. + +- Only the tile, stipples and glyphs are always synchronized. + +- The height of glyphs region has been doubled to obtain a better vi- + sual effect after the synchronization. + +- Fixed a problem causing the background pixmaps to be used also if + they were not fully synchronized. + +- Added a function to convert a PolyPoint in a dirty region. The fun- + ction is now disabled because it is not advisable to use the exten- + ts. + +- The XCopyArea is not requested if the clip region is NIL. + +- The nxagentPutImage does not update the framebuffer when it is + doing a synchronization. + +- Moved all the code handling the drawables synchronization in the + Drawable.c file. + +- As the shared memory pixmaps are never synchronized with the re- + mote X server, now they're marked as dirty when they're created. + +- An XFillRectangles request now marks the rectangles of the desti- + nation drawable as synchronized. + +- Fixed a bug that was causing the CopyArea to propagate wrongly the + corrupted region on the destination drawable when the GC uses a + clip mask. + +- Implemented a test function useful to show on the windows all the + dirty regions as colored rectangles. It is used with the CTRL+ALT+A + keystroke. + +- Before sending the XRenderComposite operations (trapezoids, trian- + gles, TriStrip, TriFan), the drawables involved are synchronized if + they are dirties. + +- Changes to shadow mode. + +- Moved the code splitting the screen shadowing updates to a separate + function. + +- Suspend the sending of updates if input is received from the user. + +- Make use of callback mechanism implemented in the nxshadow library + to suspend screen polling when input is received from the user. + +- Flush the display link when requested by the proxy. + +nxagent-3.0.0-15 + +- Print the following info when the screen is resized: "Info: Resized + screen [] to [x]. + +- Changes to comply with nxshadow library. + +- Fixed the height of screen updates in shadowing mode. + +- Terminate cleanly if shadowing initialization fails. + +- Split shadowing screen updates in smaller rectangles for slow links. + +nxagent-3.0.0-14 + +- Fixed a compilation error in NXrender.c. + +nxagent-3.0.0-13 + +- Changed the LICENSE file to state that the software is only made + available under the version 2 of the GPL. + +- Added file COPYING. + +- Updated the files imported from X.org to the 6.9.0 release. + +nxagent-3.0.0-12 + +- Fixed compilation on Sun platform. + +nxagent-3.0.0-11 + +- Implemented an algorithm adapting colors if the target display have + different depth than the shadowed display. It requires that visuals + are TrueColor and depths are 16 or 24 or 32. + +- Added the option shadowmode. If this option is '0' the shadowing + session doesn't interact with the attached session. + +nxagent-3.0.0-10 + +- Changes to comply with the nxshadow component. + +nxagent-3.0.0-9 + +- Applied changes to files imported from X.org sources. + +- Updated copyright notices to the current year. + +nxagent-3.0.0-8 + +- Imported changes up to nxagent-2.1.0-17. + +- Fixed problem with font path on Solaris 10. + +- Disabled some log messages. + +- If the agent has blocked when trying to write to the display, try to + read other events from the connection. + +- After synchronizing expose events, the result of subtraction is not + sent immediately, but added to a region. Expose events will be for- + warded to clients after exiting from the event loop. + +- Critical output is set when button mouse events are received. + +- Fixed TR12D01584. X11 sessions could not be started on Mandriva Li- + nux 2007 because of a different location of fonts. The font path + used by this distribution is now added to the alternates font paths. + +- Fixed TR11D01550. Modified the collection of visuals when nxagent + opens a display. Now we only use the ones with the same depth than + the default one set in the screen. + +- Modified the reconnection of pict-format structures, to avoid an + error that arises when migrating a session by a Linux machine to + a Windows one. + +- Small changes in handling of expose events. + +- GraphicsExpose are no more forwarded to clients immediately. They + are merged with remote-only exposures and sent later. + +- Invalidated expose queue elements dealing with destroyed windows. + +- Cleaned up code in nxagentSynchronizeExpose(). + +- Fixed TR10D01541. Now when destroing a window if lastClientWindowPtr + point to this window then in nxagentClearClipboard() we put nxagent- + ClearClipboard to NULL and lastClientStage to SelectionStageNone. + +- Fixed a problem with LazyLevel option that wasn't correctly read + from command line. + +- Fixed an arithmetic exception raised when the viewable corrupted + region is empty but not nil. + +- Removed the obsolete 'sss' option. + +- Fixed a warning related to the expose queue. + +- Modified the queue of exposed region to remove some memmov() calls. + +- Remote expose events not having entries in the queue are collected + in a global region and sent later, instead of being sent immediate- + ly. + +- Changed nxagentCheckWindowConfiguration() to prevent unuseful calls + to XQueryTree(). + +- Fixed TR10D01530. Fixed an invalid write in doOpenFont(). + +- Fixed some invalid write/read in nxagentVerifyDefaultFontPath(). + +- Fixed TR10D01518. If needed, a restack is performed on the top level + windows in rootless mode. + +- Fixed TR10D01520. Reviewed session termination and log messages in + the case of indirect XDMCP. + +- In PictureCreateDefaultFormats(), cleaned the PictFormatRec struct + when the format is not supported. + +- Fixed TR09D01498. As it is possible to use multiple paths where to + store the fonts, now the agent concatenates all the existing font + paths used in various XFree/Xorg distributions to obtain a unique + default font path. + +- Fixed TR09D01502. The privates of the real pixmap are initialized + before trying to allocate a virtual pixmap, avoiding the possibility + to access an inconsistent structure in case the allocation fails. + +- Fixed a memory leak due to a missing deallocation of a virtual pix- + map's region. + +- Fixed TR08D01486. Removed a warning in NXrender.c. + +- Implemented FR08D01470. Now in the reconnection phase missing fonts + are replaced by the most similar picked among the available ones. + +- Fixed TR08D01480. A condition inside the nxagentWindowExposures + function was ignoring the possibility that the first region para- + meter could be a null region. + +- Fixed TR06D01409. Now NXCollectGrabPointer() is called with the + owner_events true in ActivatePointerGrab() . + +- Fixed TR03D01317. Increased the time after wich the session termina- + tes. + +- Fixed TR08D01475. In rootless, ConfigureWindow requests are only + forwarded to the X server, even if no window manager has been detec- + ted. + +- Fixed TR04D01367. An XKB event is sent to notify that keyboard map- + ping has changed. + +- Check the number of regions in the list before running nxagentSynch- + ronizeExpose(). + +- Reduced the number of GCs used during the drawable synchronization. + +- Optimized the corrupted region synchronization trying to use the + extents is some circumstances instead of split the full region. + +- Checked and removed some FIXME. + +- Fixed TR05D01384. Xgl server uses less picture formats than nxagent + usually does. Now the PictFormat structures used by nxagent are fil- + tered with the ones available for the real display. + +- Fixed TR06D01410. Function nxagentRestoreAreas have to make use of + a GC with subwindow mode ClipByChildren for preventing from repaint + also children of restored window. Children are restored in a separ- + ate call, if they have backing store on. + +- Fixed TR07D01426. The cursor data were swapped in place if the dis- + play had different bitmap bit order. Let Xlib do this work on a copy + of the image, preventing from messing up the original data. + +- Fixed TR07D01450. Some fonts were missing in the list of available + fonts because the ListFonts pattern used to build this list was too + much generic. To build a full font list two different patterns have + been used. + +- Fixed TR07D01449. Some X clients might affect the X screen saver + functioning modifying the default properties. The SetScreenSaver + request now correctly checks the parameters changes to avoid any + issue. + +- Fixed TR07D01432. X11 sessions could not be started on Debian 'Etch' + because of a different location of fonts. The font path provided by + the Debian Policy is now added to the alternates font paths. + +- Fixed TR07D01437. The auto suspend timer was reset when it should + not. + +- Fixed a conditional jump on uninitialised value. + +- Fixed TR05D01380. Now migrating a session when display have a 16-bit + depth does recover all visuals, avoiding reconnection failure. + +nxagent-3.0.0-7 + +- Fixed problems occurring when the main session is terminated and the + connection is refused to the shadow agent. + +- Fixed include directory order for Solaris. + +nxagent-3.0.0-6 + +- The shadow agent works only in viewport mode. + +- Added nxagentShadowCreateMainWindow function. This function creates a + pixmap and a window for mirroring the display root window. + +- Added NXShadowUpdateBuffer() function in order to create the buffer + for the poller with the same sizes of the root window of the master + agent. + +- Added NXxrandr.c NXxrandr.h and NXxrandrint.h files. + +- If the main agent screen is resized, the shadow agent adapts to the + new size of the root window. + +- Changed option activating mirror to -S. + +- Removed usleep() call when the agent is suspended. + +- Input events are sent to the main session even if it is in sus- + pended state. + +- Updates are made from top to bottom. + +- Added the option IgnoreVisibility. If this option is set, PutImage + is not skipped when the window is fully obscured. + +- Added the option 'shadow' saying the display to attach. + +nxagent-3.0.0-5 + +- Added the mirror mode. It is activated by -M option. + +- Recovered the state of keys when the agent in access mode loses + focus in mirror mode. + +- Changes to work with 16-bit depth display in mirror mode. + +- Changed the Imakefile in order to include NXaccess.h and NXaccess- + Event.h files. + +- The layout keyboard is passed to NXShadowCreate() function in order + to load the right keymap file in mirror mode. + +nxagent-3.0.0-4 + +- Small changes to build on 64 bit x86 platform. + +nxagent-3.0.0-3 + +- Fixes to build on Cygwin platform. + +- Change the order of include directories in Imakefile. + +- Renamed GC.h, Window.h and Pixmap.h to avoid name clashes. + +- Undefined NXAGENT_UPDRADE in Composite.c and NXcomposite* files. + +- Defined ddxBeforeReset() in Init.c. + +nxagent-3.0.0-2 + +- Merged changes to NXdispatch.c, NXdixfonts.c, NXmiwindow.c, NX- + picture.c, NXproperty.c, NXrender.c, NXresource.c, NXwindow.c. + +nxagent-3.0.0-1 + +- Opened the 3.0.0 branch based on nxagent-2.0.0-88. + +nxagent-2.0.0-88 + +- Fixed a memory leak in the code handling the remote font list. + +- Removed some log message. + +nxagent-2.0.0-87 + +- The box size is checked during the region synchronization to avoid a + possible arithmetic exception. + +nxagent-2.0.0-86 + +- Checked the validity of the colormap in nxagentChangeWindowAttri- + butes(). + +nxagent-2.0.0-85 + +- Fixed the bad destination coordinates of shared memory pixmap synch- + ronization in nxagentCopyArea() and nxagentCopyPlane() functions. + +nxagent-2.0.0-84 + +- Discard the Terminate Server key sequence Ctrl-Alt-BackSpace. + +nxagent-2.0.0-83 + +- Added a workaround to prevent the use of an inconsistent client poi- + nter in the nxagentNotifyConvertFailure() function. + +nxagent-2.0.0-82 + +- Fixed the parsing of option 'backingstore'. + +nxagent-2.0.0-81 + +- The agent window visibility on the real X server is used together + with the internal state to decide if graphics operations can be + avoided. + +- When restoring areas, if the backing pixmap is corrupted, an expose + event is sent to the region that can't be restored. + +nxagent-2.0.0-80 + +- The core protocol requests internally used to accomplish a Render + extension request are no longer propagated to the real X server. To + be more precise in this way we can save many XCreatePixmap, XChange- + GC and XSetClipRectangles. + +- Corrected a minimal incoherence in nxagentCopyArea in managing the + creation and deallocation of a region. + +- Fixed a double synchronization of an aged drawable during a put ima- + ge operation, due to a missing check of nxagentSplitTrap value. + +- Added the VisibilityChangeMask bit to the event masks. + +- Improved the algorithm which prevents the server client's resource + duplication. + +nxagent-2.0.0-79 + +- Added the 'lazylevel' option usable in the command line to specify + how much the Agent should be lazy. The default level is 2. Each + level adds the following rules to the previous ones: + + Level 0 The lazy is off. + + Level 1 The put images are skipped if we were out of bandwidth, + unless that the destination drawable has an old corru- + pted region. + + Level 2 No data is put or copied on pixmaps, marking them always + as corrupted and synchronizing them on demand. + + Level 3 The put images over the windows are skipped marking the + destination as corrupted. When a copy area to a window is + requested, the source is synchronized before copying it. + + Level 4 The source drawable is no longer synchronized before a + copy area, but the operation is clipped to the synchro- + nized region. + +- Implemented a dynamic synchronization mechanism, based on user ac- + tivity: if the input devices are not used for a variable amount of + time (depending from the configured link type), the synchronization + starts and goes on until there is enough bandwidth. + +- Minor fixes to the way the copy area propagates the corrupted re- + gion. + +- Whenever a put image is done, a full synchronization is forced on + the destination drawable if it has an old corrupted region. + +- During the overall synchronization a drawable is skipped if its + timestamp is lower than the synchronization interval. + +- Updated the copy plane to skip the operations from a corrupted pix- + map to another pixmap. + +- Fixed the pixmaps synchronization which was not checking the avai- + lable bandwidth. + +- In rootless mode, ConfigureWindow requests are not internally per- + formed for top level windows if a window manager is running. Anyway + they are forwarded to the X server. + +- Enabled the DPMS extension. + +- Fixed the -dpi option. + +nxagent-2.0.0-78 + +- When the remote proxy supports the alpha encoding, the alpha data + is sent compressed. When connected to an old version, the agent + uses the NXSetUnpackAlphaCompat() call. + +- Added support for the RLE pack method. + +nxagent-2.0.0-77 + +- Fixed the check for special keystrokes. State mask for Alt and Meta + keys are inferred from the X server modifier map. + +nxagent-2.0.0-76 + +- Fixed application icon in rootless mode. + +- If SYNC_WHOLE_GLYPH_DRAWABLE is set in Render.c the whole drawables + used in the composite glyphs are synchronized. This is useful to + evaluate the policy we should use to minimize the put images. + +- Code cleanup in Pixmap.c concerning the synchronization functions. + +- Added the nxagentSynchronizeBox() function. + +- Setting a wide band link (ADSL, WAN, LAN) disables Lazy and Strea- + ming options. + +- Now the Lazy option can be switched by the Ctrl+Alt+E keystroke. + +- Set a timestamp on a drawable to verify how much old its data are. + If we didn't update it since two seconds, the put image operations + are not skipped. + +- The image data split in chunks smaller than a threshold is now mo- + ved from the nxagentPutImage() to the nxagentRealizeImage() func- + tion. If a chunk is going to be put on an hidden area of a window, + the operation is skipped. + +- Fixed the value assigned to the id of the alpha visual. Now it is + assigned by XAllocID(). + +- Removed a call to XSetInputFocus() before mapping the default win- + dows. + +- Restored the backup display pointer when failing to reconnect the + display. + +- Fixed some return value in the options parser function. + +- Fixed the parsing of environment variable. + +nxagent-2.0.0-75 + +- Optionally split the long X_RenderTrapezoid requests in multiple + messages to help the compression. + +nxagent-2.0.0-74 + +- Fixed a bug preventing the reconnection of pictures. + +- Fixed the way the agent notify its start up to NX Client. Now the + ownership of agent atom is set before the reconnection of pixmaps. + +nxagent-2.0.0-73 + +- Added a check on the display pointer in nxagentTerminateDisplay() + to ensure that we don't try to force an I/O error if the display + is already down. + +- The image operations now are clipped to the visible area of the + drawable. As this may hamper the caching algorithm, only source + images bigger than 32K are clipped. + +- Code cleanup in Render.c. + +- When setting SKIP_LOUSY_RENDER_OPERATIONS in Render.c the realiza- + tion of some operations is skipped. This is useful to determine + how clients (mis)use the RENDER extension to achieve even worse + performance than they were able to achieve using the core protocol. + +nxagent-2.0.0-72 + +- Ensured that SIGUSR1 and SIGUSR2 are ignored if the NX transport + is not running. + +nxagent-2.0.0-71 + +- Modified the following messages used to track the session state: + + From: "Session: Session starting at..." + To: "Session: Starting session at..." + + From: "Session: Session terminating at..." + To: "Session: Terminating session at..." + +nxagent-2.0.0-70 + +- Removed the obsolete 'Info' messages related to the 'fast' versus + 'slow' copy area and get image modes. The -slow and -fast options + are now ignored as ignored are the keystrokes that allowed switch- + ing between the two modes. + +- Removed more obsolete warnings and commented the logs left around + for test purposes. + +- Removed the code in NXdispatch.c handling the fake get-image. + +- Removed the flags related to the use of the frame-buffer. + +- Major code cleanup in GCOps.c, Window.c, GC.c, Pixmap.c, Screen.c. + +nxagent-2.0.0-69 + +- Added a check to avoid parsing an empty DISPLAY variable. + +- Added parsing of the 'streaming' option. + +- GetTimeInMillis() function is compiled only if DDXTIME is defined, + to avoid double definition errors on Solaris platform. + +- Messages "Suspending session..." and "Session suspended..." are not + printed if the DE_TERMINATE dispatch exception is set. + +- When synchronizing the shared memory pixmaps the image is no longer + put on the framebuffer. + +- Code cleanup in the nxagentSynhronizeRegion() function. + +- Added the 'lazy' option to enable or disable the lazy policy. It is + activated by default. At the moment this is configured at compile + time and can't be changed through a command line or the option file. + +- Fixed the counter of the corrupted backgrounds by checking if the + pixmap was already marked. + +- The option SharedPixmaps is now activated by default. + +- Fixed a problem when synchronizing the shared memory pixmaps with + the operation being erroneously skipped. + +nxagent-2.0.0-68 + +- If we are doing a copy area to a pixmap and the source drawable is + not synchronized, the destination is marked as corrupted and the co- + py area request is not propagated to the X server. As a general rule + the source drawables are now synchronized only when they are copied + to a visible window. + +- The nxagentSynchronizeRegion() function synchronizes the region one + box at a time. This solves the incorrect pictures synchronization. + +- When a new element is added to the list of exposed region, sending + the synchronization request to the X server is postponed to the next + call of nxagentFlushConfigureWindow(). + +nxagent-2.0.0-67 + +- Ensured that NXTransDestroy() is called when getting rid of the NX + transport. + +nxagent-2.0.0-66 + +- The various messages used by the NX server to control the state of + the session have been changed and the NX server will have to be mo- + dified accordingly. + + At the early startup the agent will print the following message: + + "Info: Agent running with pid '...'." + + Followed by: + + "Session: Session starting at '...'." + + The ellipsis here represent the current timestamp, as reported by + the POSIX function ctime(): + + Example: Mon May 22 15:07:11 2006. + + After the connection to the remote display has been established, + the agent will print the following message: + + "Session: Session started at '...'." + + This replaces the old messages: + + "Info: Session started, state is [SESSION_UP]." + + Or: + + "Info: XDMCP session started, state is [SESSION_UP]." + + And: + + "Info: Entering dispatch loop with exception 0x0." + + If the display connection can't be established, due to a network + failure, for example, the agent will exit with a fatal error, for + example: + + "Fatal server error: + Error: Unable to open display 'nx/nx,options=...'." + + This is a special case, as the X server is still initializing and + the agent can't intercept all the possible causes of errors. + + When suspending the session, the agent will print one of the fol- + lowing messages, depending on the reason of the disconnection: + + "Session: Suspending session at '...'." + + Or: + + "Session: Display failure detected at '...'." + "Session: Suspending session at '...'." + + As soon as the disconnection procedure is completed, the agent will + notify the server with the message: + + "Session: Session suspended at '...'." + + This message replaces the old message: + + "Session: Session suspended." + + When entering the reconnection procedure, the agent will print: + + "Session: Resuming session at '...'." + + If the session can be successfully resumed, the agent will print: + + "Session: Session resumed at '...'." + + Otherwise, if the display cannot be opened or if the proxy is not + able to negotiate the session, the agent will return in suspended + mode by printing: + + "Session: Display failure detected at '...'." + "Session: Session suspended at '...'." + + At the time the session be terminated, the agent will print: + + "Session: Session terminating at '...'." + + Followed by: + + "Session: Session terminated at '...'." + + This replaces the old message: + + Info: Exiting dispatch loop with exception 0x2. + + The message 'Session terminated at...' should be the last message + parsed by the NX server. From that moment on the NX server will + wait the agent process to ensure that the cleanup procedures are + completed without errors and that the process successfully termi- + nates with the exit code 0. + +nxagent-2.0.0-65 + +- Many improvements to the block handler and to the drawable synch- + ronization loop. + +- Anyway the synchronization loop is skipped, at the moment, to bet- + ter test the new copy area implementation. Also all the put-image + on pixmaps are skipped, so that the pixmaps are only synchronized + on demand. + +- Small fix in the put image to always use the region already allo- + cated when marking a region as corrupted. + +nxagent-2.0.0-64 + +- The realization of the put image operations now depends on the + state of the link, as reported by the proxy through the synchroni- + zation handler. If the proxy link is aproaching a congestion, the + destination area of the drawable is marked as corrupted and the + operation is skipped. + +- At the moment the synchronization strategy is quite unsophistica- + ted. The drawables are synchronized when a timeout expires in the + block handler. The synchronization loop is aborted as soon as the + link approaches again the congestion and is restarted at the next + timeout. + +- Imported miwindow.c from the DIX layer. The code has been changed + to prevent miSetShape() from trying to destroy a null region. The + bug appears to be related to the backing store but it is unclear + if can also affect the sample server. The region is allocated at + the beginning of the function only if the backing store is set for + the window. Then miSetShape() calls miChangeSaveUnder(), that, in + turn, calls miCheckSubSaveUnder(). The latter can change the back- + ing store attribute of -some- windows, including, apparently, the + window that miSetShape() is processing. miSetShape() then destroys + the region if the backing store is set, but it doesn't verify if + the region was actually allocated. The problem is fixed by simply + adding a check on the pointer. + +nxagent-2.0.0-63 + +- Added the nxagentDisplaySynchronizationHandler() callback. The NX + transport uses the callback to report when it is possible synchro- + nize the pixmaps and the other X objects that are corrupted or in- + complete. + +- Fixed nxagentClearSelection() to correctly validate the selection + owner before clearing the record. + +- Changed the NXGetControlParameters() call to reflect the changes + to the reply. + +nxagent-2.0.0-62 + +- At reconnection the pixmap data is sent to the remote X server only + in two cases: if the pixmap is associated to a picture (glyphs, for + example) or if its depth is 1 (clip masks of GCs). All the other + pixmaps are marked as corrupted and synchronized on demand as soon + as the drawable is used as a source. This code is not enabled by + default and is currently being tested. + +- Implemented a new copy area function synchronizing the corrupted + region of a drawable before using it as a source. + +- Imported resource.c from the DIX. This makes possible to avoid the + duplication of the RT_GC, RT_FONT and RT_PIXMAP resource types. + +- Added the RT_NX_GC resource type and removed the old code dealing + with the reconnection of the GCs used by the GLX extension. + +- Fixed a problem in the synchronization of the window background. + +- Checked and removed some FIXMEs related to the streaming code. + +- Changed nxagentRestoreAreas() to take care of the width of the win- + dow's border. + +- Changed nxagentSaveAreas() to be independent from the window's pos- + ition. + +- Called nxagentMapDefaultWindows() before pixmaps' reconnection. + +- Changed nxagentMapDefaultWindows() to notify the client about the + agent's startup also when running in rootless mode. + +- Added the delete and backspace keystrokes to the routine removing + duplicated keys. + +- Wehn resizing the desktop the clip region of the children windows + is clipped to the new size of the root. This fixes a crash occur- + ring when resizing the desktop to the minimum height. + +nxagent-2.0.0-61 + +- Changed the extraction of alpha channel from images to be endianess + independent. + +nxagent-2.0.0-60 + +- nxagentReleaseSplit() now uses the NXAbortSplit() request to force + the proxy to discard the pending splits. + +- Added the value of the SharedMemory and SharedPixmaps options in + the log, together with the size of the shared memory segment used + by the remote proxy. + +- Fixed the compilation problem affecting the previous version. + +- The location of xkb base directory is checked by calling _NXGetXkb- + BasePath() function. + +- Fixed TR05D01371. nxagentVerifyDefaultFontPath() is called only if + the default font path is not defined on the command line. + +- Removed some log message. + +nxagent-2.0.0-59 + +- Improved the composite text operation to synchronize the regions + affected by the operation instead of the whole drawable. + +- Updated the copy plane to better propagate the corrupted region + to the destination. + +- The background pixmaps are synchronized with a deferred strategy. + Tiles and stipples are still synchronized as soon as the GC needs + to be used. + +- Completed the new copy area implementation. + +- Shared memory pixmaps are not synchronized after a RenderChange- + Picture operation. This needs further testing. + +- Added a nxagentNotifyKeyboardChanges() function that sends a Map- + pingNotify event to clients when the keyboard is reloaded or re- + configured. The SendMappingNotify() function is not used anymore. + This hopefully solves the TR01D01284. + +- Moved the nxagentResetKeyboard() function in Keyboard.c. + +- Checked if the previous sibling of a window is changed before try- + ing to restack it. This saves the redundant window configuration + requests of the previous version. + +nxagent-2.0.0-58 + +- Before composite glyphs operations, only areas intersecting the + glyphs extents are synchronized. + +- When a new split resource is allocated, a copy of the GC used by + the put image operation is created. Such copy will be safely used + by the commit operation even if the original GC is changed or + destroyed. + +nxagent-2.0.0-57 + +- Region saved by the backing store and corrupted region of backing + store pixmaps are emptied at suspend and resume time. This makes + the exposures go to the clients that will redraw their windows. + +- Changed the nxagent root window cursor. The cursor of the parent + window is used instead of the default 'X' cursor. + +nxagent-2.0.0-56 + +- Rewritten the state machine handling the streaming of the images. + +- By calling FatalError(), the normal server shutdown was skipped + and left the X server socket in .X11-unix. This happened also if + for any reason the agent couldn't complete the session startup. + Now the DDX abort routine, if the agent is not exiting because of + an exception, calls nxagentAbortDisplay() which closes down the + well known sockets. + +- Upon a failure of the reconnection procedure, if the alert shown + to the user by leveraging the proxy control channel is not set + to a valid code, the function in will use a default. + +nxagent-2.0.0-55 + +- Added an explicit link flush in the display block handler. The + block handler should now be called by nx-X11 before entering the + select, not only the the agent has entered WaitForReadable() or + WaitForWritable(). + +- Removed the checks on the value of the Streaming option. The way + a drawable is treated only depends from its previous state. + +- Started reimplementing the copy area operation to better propaga- + te the corrupted region to the destination. + +- Shared pixmaps are now synchronized before a copy plane operation. + +- The unpack alpha is discarded before the drawable synchronization. + This fixes the problems with the synchronization of the cursor. A + better way to deal with the condition is to be considered for the + future. + +- Added a check in the nxagentPutImage() function to skip the opera- + tion if the window is fully obscured. + +nxagent-2.0.0-54 + +- Fixed a bug in nxagentPaintWindowBackground(). A region passed as + parameter was modified by this function and this affected subseq- + uent operations involving the region. + +- In rootless mode, the map state of a top level window is uncondit- + ionally reflected in the internal state when receiving a map event + from the real display. + +nxagent-2.0.0-53 + +- Regions are marked as synchronized after an image operation if the + image didn't generate a split. + +- When an image operation takes place on a drawable which is already + being streamed, the resource is marked as invalid and the commits + are discarded. + +- A specific trap is used at the time a drawable is synchronized. + +- Fixed Render.c to use the latest streaming code. + +nxagent-2.0.0-52 + +- Fixed a problem in rootless mode where some windows could have mis- + sed to update the mapped flag after a MapNotify event. + +nxagent-2.0.0-51 + +- Realization of images is skipped, if the link is down, and a small + delay is introduced before returning from the image function. + +- Started implementing a new handler to let the agent include arbit- + rary data in the transport statistics. For now, only the interfa- + ces and the stubs exist, and the handler is not registered to the + proxy. + +nxagent-2.0.0-50 + +- Removed the unused code in nxagentCheckPixmapIntegrity(). + +- Instead of calling nxagentShapeWindow() immediately, windows to be + reshaped are added to the list of windows that have to be configur- + ed at later time. This allows SaveAreas() to work even when windows + change shape, as in the case of the "bouncing cursor" as implement- + ed in some versions of the KDE. + +- Added a missing call to nxagentFlushConfigureWindow() in the recon- + nection procedure. + +nxagent-2.0.0-49 + +- Code cleanup in the lazy encoding. Implemented distinct utilities + to allocate the split resources and manage the corrupted areas. + +- The Render.c file is taken from the previous version because the + updates break the composite code. + +- Renamed the option 'Lazy' to 'Streaming'. + +nxagent-2.0.0-48 + +- Made the image cache use the agent data, instead of allocating and + copying. + +- Fixed a memory leak in the image routines. + +- The image cache is freed at exit. This helps investigating other + eventual leaks. + +nxagent-2.0.0-47 + +- Solved the problem at reconnection with lazy encoding enabled. + +nxagent-2.0.0-46 + +- Solved a bug in the parsing of the pack method that made the agent + select an unavailable id. + +nxagent-2.0.0-45 + +- Ensured that images are explicitly byte swapped before sending to + an X server using a different byte order. In the attempt of saving + an expensive operation, the previous code let the unpack procedure + do the job, but this could fail to work in some special cases. + +- Cleaned the bitmaps used for the core cursors before putting the + image. + +- Left the display error handler installed during all the lifetime + of the session so that other parts of the code don't have to inst- + all it explicitly before entering a critical Xlib routine. + +- Removed more unused code. + +nxagent-2.0.0-44 + +- Fixed the problem with the cursor image being encoded with a lossy + method. The fix is a temporary. The final solution requires changes + to the lazy encoding. + +- Reworked the code dealing with the alpha visual. The color mask is + set based on the endianess of the remote display and is recreated + after a session resume. + +- Removed more unused code. + +nxagent-2.0.0-43 + +- Corrupted regions are now correctly clipped to the visible area of + the drawable. + +- Fixed a problem with the clip mask when calculating the intersect- + ion of the clip region with the destination region. + +- Drawables involved in a composite glyph operation are now synchro- + nized prior to being used. + +- The nxagentRealizeDrawable() function is now called only for draw- + ables that are not already synchronized. + +- Pixmaps are now skipped in the synchronization loop. Synchronizat- + ion of pixmap is to be implemented. + +nxagent-2.0.0-42 + +- Improved the algorithm removing the duplicated keys by trying to + read more events. + +nxagent-2.0.0-41 + +- Made use of the NXFinishSplit() request to speed up the completion + of a pending split. + +- Added an explicit NX transport flush before any operation that may + block waiting for data from the X server. + +- Set the NX flush policy to deferred after reconnection. + +- Solved refresh problems when reconnecting in rootless mode. + +- Modified the routine removing duplicated arrow key events. Now the + routine deals with page down and page up keys as well. + +- Added a check for xkb base directory path, in order to support new + Linux distributions. + +- Disabled backing store support for rootless sessions, as implement- + ation is not very functional, yet. + +nxagent-2.0.0-40 + +- Removed code related to old managing of backing store. + +- Added initialization of backing store by calling miInitializeBack- + ingStore(). + +- Implemented nxagentSaveAreas() and nxagentRestoreAreas() functions. + These functions are based on fb code. Calls to XCopyArea() have been + added in their implementation to make them be effective also on the + real X server. + +- Instead of calling nxagentConfigureWindow() in ClipNotify() and + PositionWindow(), windows to be configured or mapped are added to a + list, together with a mask storing operation that have to be done. + Windows in the list will be configured or mapped later by calling + nxagentFlushConfigureWindow(). This avoids that windows were mapped + or configured before saving areas in the backing store pixmaps. + +- The function nxagentFlushConfigureWindow() is called before resto- + ring areas on the X server in nxagentRestoreAreas() and at the end + of ConfigureWindow and MapWindow in the DIX layer. + +- Blocked the NoExpose events at the proxy side. + +- Fixed an error in nxagentCompareRegions(). + +nxagent-2.0.0-39 + +- Ensured that the display errors are detected while waiting for a + split operation to complete. + +- Removed more unused code. + +nxagent-2.0.0-38 + +- Changed nxagentSetCursorPosition() to avoid warping the cursor if + the requesting client is NULL or the serverClient. + +- Added a specific trap to avoid compressing an image associated to + a RENDER cursor using a lossy encoding. + +nxagent-2.0.0-37 + +- Added a check in nxagentPaintWindowBackground() to avoid calling of + XClearArea() if the window is not realized. + +- Modified nxagentAtomNames in Atoms.c to include CLIPBOARD and TIME- + STAMP atoms, avoiding further calls to XInternAtom in Clipboard.c. + +- Solved TR04D01356. Auto repeat mode setting is no more propagated to + the X server keyboard. + +- Cleaned up the code in the routine removing duplicated arrow key + events. + +nxagent-2.0.0-36 + +- Added the Literals.h file. For now it just contains a table used + to translate a request opcode to the name of the X request, to be + used for test purposes. + +nxagent-2.0.0-35 + +- Major code rewrite in nxagentPutSubImage(). Removed support for the + deprecated image encodings. Ensured that padding bytes are cleaned + before trying to locate the image in the nxcompext cache. Avoided + to store the image in the cache if it is coming from a XVideo or + GLX operation. + +- Added support for the new RGB image encoder. This allows the agent + to use the simplest encoding by still separating the alpha channel + from the image data. + +- Added the missing check in nxagentRedirectWindow() verifying that + use of the composite extension is enabled. + +- Updated to use the new NXCleanImage() function. + +- Removed more debugging output. + +nxagent-2.0.0-34 + +- Updated to use the 'what' parameter in NXFlushDisplay(). + +- Removed the duplicated arrow key events from the event queue. + +- Solved the TR04D01355. The X11 agent now tries to locate the + fonts.dir file in the misc directory, to verify the validity of + the font path. + +- Added a check in nxagentChangeClip to avoid creating a new clip + mask if the old clip mask matches the former. + +- Use the 'fixed' font to replace fonts that are not found a the + display reconnection. This should overcome one the most common + sources of troubles when migrating the session to a different + display, and constitute the base for improving the algorithm + trying to match a substitute font. + +- Implemented the FR04D01360. Now the user can enable/disable the + streaming of the images by using the option 'streaming'. + +- Implemented the FR04D01358. The backing-store can be enabled or + disabled by using the option 'backingstore'. + +- Forced the reconnection routine to call the IOError handler in + the case the display cannot be opened. + +nxagent-2.0.0-33 + +- The GetImage requests in 'slow' mode are now served by retrieving + the content of the drawable from the frame buffer. + +- Replaced a call to XQueryExtension() by one to XRenderQueryExten- + sion(). This function caches previous QueryExtension requests. This + partially implements FR01D01275. + +- At reconnection, the keyboard is reset only if the keyboard option + has been changed. + +- Fixed the fonts reconnection procedure. Now the remote fonts list + is refilled before fonts reconnection and after failed fonts + reconnection, so as to store the correct list of available fonts. + +- Added a check in nxagentLoadQueryFont to look up selected font in + the list of available fonts. This check avoid filling FontStruct + with invalid data. + +- Added TIMESTAMP to handled selection targets. + +nxagent-2.0.0-32 + +- Implemented FR03D01323. Added the 'clipboard' option to enable or + disable copy and paste operations from the user's desktop to the NX + session or vice versa. This option can take four values: + + client The content copied on the client can be pasted inside the + NX session. + + server The content copied inside the NX session can be pasted + on the client. + + both The copy & paste operations are allowed both between the + client and the NX session and viceversa. + + none The copy&paste operations between the client and the NX + session are never allowed. + +nxagent-2.0.0-31 + +- Implemented FR03D01337. Now the X11 agent is able to read the op- + tions from different places according to the following order: the + DISPLAY variable, the options file, the command line. + +- Implemented FR03D01347. Added 'composite' to parsed options. + +- Always activate shared memory support in the remote X server proxy. + +- Modified nxagentCopyArea for the case the source is a shared memory + pixmap. The pixmap on the X server is not synchronized, but the con- + tent of the shared pixmap mantained by the agent is placed directly + on the destination drawable. This allows to skip the following Copy- + Area operation. + +nxagent-2.0.0-30 + +- Added the missing flush of the Xlib buffer at the beginning of + the block handler. + +nxagent-2.0.0-29 + +- Changes in the block and wakeup handlers to queue multiple reads + and flush the link on demand. + +- Removed the unused code in Control.h and Control.c. Renamed the + files as Client.h and Client.c. + +- Added support for the '-nocomposite' command line option. + +nxagent-2.0.0-28 + +- Moved the composite code to Composite.h and Composite.c. + +- Redirected the top-level windows when running in rootless mode. + +nxagent-2.0.0-27 + +- When the composite extension is supported by the remote display, + the agent window is redirected to the off-screen memory of the + X server. + +- Imported Xcomposite.c, Xcomposite.h and xcompositeint.h from the + 3.0.0 branch to be able to activate the off-screen redirection of + the top level windows. + +- Added Composite to the list of agent options. The default is to + use the composite extension, when available. + +nxagent-2.0.0-26 + +- Avoided to suspend the clients on excess of karma or after a get + input focus request. + +- Images are now split only when the agent is in congestion state. + +- Moved all the image related functions from GCOps.h and GCOps.c to + Image.h and Image.c. + +- Removed the unused includes in GCOps.c and Image.c. + +- Added the karma delay field to the NXGetControlParameters() call. + +- Renamed placeholder.xpm as nxmissing.xpm. Renamed the Icon.h file + as Icons.h. Added there a define to point at nxmissing.xpm in the + include. + +nxagent-2.0.0-25 + +- Implemented the FR03D01334. Option keyboard is now a synonym of + option kbtype. + +nxagent-2.0.0-24 + +- Ensured that the split procedure is completed before executing a + render operation that required a synchronization of a shared mem- + ory pixmap. + +- Added the appropriate checks to avoid synchronizing the same sha- + red memory pixmap multiple times. + +nxagent-2.0.0-23 + +- Imported changes to NXrender.c and NXshm.c in the files for the + 3.0.0 port. + +nxagent-2.0.0-22 + +- Implemented FR03D01331. Options shpix and shmem enable/disable the + use of shared pixmaps and shared memory extension. + +- Implented handling of value "query" for nxagentKbtype. This value + is passed by the NX client for MacOSX. If value of nxagentKbtype is + "query" or NULL we init keyboard by core protocol functions reading + the keyvoard mapping of the X server. The property _XKB_RULES_NAMES + is always set on the root window with default values of model and + layout. + +- Fixed TR11C01223. When the XDM connection can't be established the + agent creates an alert to notify the user that XDM session failed + to start. + +- Changed Clipboard.c to fix invalid read errors in nxagentGetClip- + boardWindow() function. + +- Implemented FR11C01218. Modified Font.c introducing the new function + nxagentLoadQueryFont, this function loads the font_struct struct + locally instead of sending a QueryFont request. + +- Modified nxagentListRemoteFontsfunction to fill nxagentFontList + struct with all remote fonts, avoiding further calls to XListFonts. + +- Added two functions, nxagentFreeRemoteFontList and nxagentFreeFont, + used in disconnect phase to empty the nxagentFontList struct and + the cached FontStruct elements, respectively. + +nxagent-2.0.0-21 + +- Updated to include the remote proxy version in the NXGetControl- + Parameter reply. + +- Updated to use the NXDisplayFlush() and NXSetDisplayPolicy() int- + erfaces. + +nxagent-2.0.0-20 + +- NXInitDisplay() and NXResetDisplay() are called at the time we + open or close the display, to let nxcompext set up its internal + structures. + +nxagent-2.0.0-19 + +- Activated the streaming of the images even in the case of a link + type LAN. + +- In NXmiexpose.c, if the number of rectangles in an exposed region + exceeds 4, we let a predicate function decide if it is better to + send the window extents, rather than the rectangles in the region. + +- Added the NXAGENT_SERVER define in the Imakefile. It will be used + in future to mark all the modifications made to files we imported + from other layers. + +- Removed the warnings from NXmiexpose.c. + +nxagent-2.0.0-18 + +- Imported NXmiexpose.c in the agent code. + +- Removed NXmiwindow.c from the agent code. We now use the original + miwindow.c + +- Removed the static qualifier from the _NXFontPath definition. + +- Started implementing the new lazy encoding mechanism. For each of + the drawables, the agent will create a "corrupted" region and will + try to synchronize the drawable when there is bandwidth available. + This is a work in progress. + +- Implemented the function nxagentFbOnShadowDisplay. This is a test + facility which opens a window on the display showing the content + of the agent's framebuffer. + +nxagent-2.0.0-17 + +- The image streaming procedure is now activated also when using a + link of type LAN. + +- Removed the call to NXTransDestroy() in nxagentCloseDisplay. The + NX transport is now implicitly shut down by either NXForceDisplay- + Error() or XCloseDisplay(). + +- Updated to comply with the new NX function prototypes introduced + in nxcomp-2.0.0-31. + +nxagent-2.0.0-16 + +- Fixed a bug in the nxagentModifyPixmapHeader function that was + causing some glyphs to be displayed incorrectly. + +- Implemented the test function nxagentPixmapOnShadowDisplay, useful + to display a pixmap on the real screen to check its consistency. + +nxagent-2.0.0-15 + +- Ensured that, before restarting a client after a no-split, all the + pending image commits are executed. + +- Installed the display error predicate function before trying to + open the display even at session startup. This prevents the agent + from disappearing silently if a failure occurs before the display + initialization is completed. + +- Moved the initialization of the callback functions in Display.c. + +- Added some interfaces to manipulate the callbacks and the error + handlers and verify the state of the display flags. + +nxagent-2.0.0-14 + +- Implemented stub versions of the nxagentDisplayCongestionHandler() + and nxagentDisplayBlockHandler() callbacks. See nx-X11-2.0.0-17. + +- Added the nxagentDisplayErrorPredicate() function. In combination + with changes implemented in nx-X11-2.0.0-16, this allows the agent + to abort a blocking operation and shutdown the display in a timely + fashion if a signal or any other error condition is received insi- + de Xlib. + +- Modified nxagentWaitSplitEvent() to use XIfEvent() as we can trust + the proxy to either send the event or give up the proxy connection. + The function will also give up when an error condition is raised, + like for example a session termination requested by the user. + +- Removed any remaining reference to the unused display buffer and + image cleanup functions. + +- Fixed exposures problems when reconnecting. + +- Solved TR05C00896. The problem was due to window manager utilizing + zero-thick-lines drawing requests. These drawing operations are now + performed by calling fbPolySegment() instead of miPolySegment(), + which doesn't handle the zero-thick-lines drawing case. + +nxagent-2.0.0-13 + +- Improved the management of the expose events. We now create the + fake window used to keep the agent synchronized with the X server + only once, instead of creating and configuring a different window + for each generated region. + +- A warning is printed if the changes requested for the fake window + don't match the changes reported in the subsequent ConfigureNotify + event. + +- Imported previous changes in NXevents.c into the 3.0.0 port. + +nxagent-2.0.0-12 + +- Activated the image streaming also during the reconnection. This + makes possible to leverage the remote disk cache. + +- Ensured that all clients are restarted when the session is suspen- + ded. This is required because the proxy is gone but we may have + some client still waiting for the completion of a split procedure. + +- Skipped the reset of the keyboard device if the display breaks at + the time it is being reconnected. + +- As the reset of the keyboard may have failed before we were able + to set a valid DeviceIntPtr, also added a check in ProcessPointer- + Event(), in NXevents.c to verify that the state of the display is + valid before accessing any of the device members. This is to be + better investigated. + +nxagent-2.0.0-11 + +- Solved TR02D01298. The clip region associated to the current glyph + was not updated because the serial number of the virtual pixmap + pointed by the picture was not incremented. + +- Imported the NXmiglyph.c file from render directory. + +- Removed the patch added in the release 1.3.2-6 temporary fixing this + problem. + +nxagent-2.0.0-10 + +- Various improvements the wakeup procedures. + +- Implemented the FR10C01110. Now, the X11 agent manages both the + PRIMARY and CLIPBOARD selections. It is possible copy and paste text + also by using Ctrl+C and Ctrl-V. + +- Modified NXdispatch.c in order to correctly include header files. + +- More cosmetic changes and code cleanup. + +- Imported changes into the files for the 3.0.0 port. + +nxagent-2.0.0-9 + +- Rewritten the procedures suspending and resuming the clients in + Control.c. This solves a problem with clients that were restarted + at wrong time and should ensure that multiple events for the same + client are correctly handled. + +- Removed the calls to NXSetUnpackGeometry() setting the parameters + for the client 0. The geometry is now set only at the right time, + just before trying to unpack the image. + +- Removed the sample code using the NXTransChannel() interface. + +nxagent-2.0.0-8 + +- Added test code showing how to open a new NX channel by using the + NXTransChannel() interface. + +- Streaming of images is not attempted in the case of link LAN. + +- Added preliminary code to the tell the proxy to flush the link if + the agent is idle. + +- Imported changes from nx-X11-2.0.0-14 in NXdixfonts.c. + +nxagent-2.0.0-7 + +- Modified exposures managing: agent synchronizes both with remote X + server and remote window manager for every generated region. Synch- + ronization is reached sending a ConfigureWindow request for a fake + window created on purpose. This way the exposures for the resulting + region coming from calculating the difference between local region + and the remote region are sent to clients in order to avoid duplica- + ted refreshes. + +- Improved new algorithm for managing exposures in order to work pro- + perly also in rootless mode: added privates to windows in order to + get information about mapping of windows on remote X server and vi- + sibility state too. This way local exposures are replaced by remote + ones if windows are mapped only for agent or windows are not fully + visible. This solves TR08C00971. + +- Window attributes values about backing store and save-under are re- + spectively set to NotUseful and False when creating a window on re- + mote X server and ignored when a client requests to change these + attributes. + +- Removed a no more needed function call to generate exposures when + resizing windows. + +nxagent-2.0.0-6 + +- Updated the NoMachine copyright notices. + +nxagent-2.0.0-5 + +- Added handling of font reconnection failure. In case of failure in + reconnecting some font, the agent adds the font server connection + forwarded by nxcomp to the font path of the X server. + +- Fixed TR09C01022. Moved the handling of the session states into + main cycle. The session states are not more handled into SIGHUP and + IOError handlers but into nxagentHandleConnectionStates() called in + nxagentWakeupHandler(). + +- In ResizeChildrenWinSize(), privates storing window geometry are + updated even if the call to PositionWindow() is skipped. This have + to be done because the window is moved by the X server accordingly + with window gravity. This prevent some window positioning error on + the real display evidenced with OpenOffice and GNOME. + +nxagent-2.0.0-4 + +- Solved TR12C01234. In some conditions Alt-F4 keystroke made the user + unable to open the Gnome Menu panel. This was due to the agent dis- + carding KeyRelease events for Alt-F4 and Alt-F2. + +- Undefined TEST and DEBUG in Dialog.c + +- Changed the NXAGENT_VERSION define from 1.5.0 to 2.0.0 + +- Caching and streaming of images is now disabled when dispatching + requests from the GLX and XVideo extensions. + +- Added the NXxvdisp.c and NXglxext.c files. These files are needed + to intercept calls to the XVideo and GLX extensions. Only files + in the main directory are imported. Files in the X directory, used + for the 3.0.0 port, for now are empty. + +- Added the nxagentXvTrap and nxagentGlxTrap flags. These flags are + set when dispatching requests from the XVideo and GLX extensions. + +- Added the GL and Xext include directories to the Imakefile to be + able to compile the NXxvdisp.c and NXglxext.c sources. + +- Modified the NXrender.c and NXshm.c files to set the nxagentGCTrap + nxagentRenderTrap and nxagentShmTrap even when dispatching requests + from swapped clients. Files for the 3.0.0 port are not updated. + +nxagent-2.0.0-3 + +- Solved a problem in the export of WM_SIZE_HINTS properties in root- + less mode on 64 bit machines. + +- Modified Render.c in order to correctly process Xrender header fi- + les on 64 bit machines. + +- Made changes in order to compile the agent in the Cygwin environ- + ment. + +- Renamed the files Time.* to Millis.* + +- Specified the relative path of some included header files. + +- In the Imakefile added a new include paths order related to the + Cygwin environment to avoid name clashes. + +- Disabled the MIT-SHM extension in the Cygwin environment. + +- Fixed TR11C01186. Added -timeout item to the usage message. + +- Fixed TR08C00945. Scrolling a document in Firefox caused image left- + overs with animated banners. Set the right window gravity on windows + created in the real X server. Let X move children for us accordingly + with window gravity attribute, without dix interferences. + +- Removed logs related to parsing of the options file. + +- Modified dialogs in order to show the name of the session in the + caption. + +nxagent-2.0.0-2 + +- Imported changes up to nxagent-1.5.0-112. + +- Fixed TR12C01241. The failure condition returned by the XQueryTree + function is managed in order to avoid the subsequent errors. + +- Fixed the TR11C01165. X11 sessions could not be started on Ubuntu + 5.10 because of the different location of fonts. Now we check the + existence of the fonts directory pointed by the default XF86 and + X.org font path and, if the directory does not exist, we use the + alternate font path used on Ubuntu. + +- Set the default value of DeviceControl option to False before resu- + ming a session. + +- Added a warning message printed if reset of keyboard fails at recon- + nection. + +- Fixed TR11C01185. Solved by checking if there are windows iconized + when a window is destroyed. + +- Fixed TR11C01164. The xkbcomp process used LD_LIBRARY_PATH as it was + a child of the agent. Added a call to NXUnsetLibraryPath() in Init.c + in order to remove LD_LIBRARY_PATH before executing a child process. + +- Check if there are windows iconized before terminating a rootless + session. + +- Modified CHANGELOG to include reference to fixed TRs TR08C00967 and + TR08C00969. Removed some typo. + +- Fixed TR11C01194. The agent crashed if launched with -kb option. + +- Fixed TR10C01042. The keyboard didn't work if the session migrated + from Apple X server to another platform and viceversa. This has been + solved by initializing the keyboard device whenever the session is + resumed. This feature can be disabled by the new option -nokbreset. + +- Fixed some compilation error arising if TEST was enabled in the file + Keyboard.c. + +- Fixed TR11C01167. During the disconnection the font structures poin- + ted by the font cache were freed leaving inconsistent data in the + corresponding privates. Now they are nullified and the GCs are che- + cked to guarantee a correct font handling in the suspended state. + +nxagent-2.0.0-1 + +- Opened the 2.0.0 branch based on the 1.6.0-11. + +nxagent-1.6.0-11 + +- Updated the NX.original copies of files in X directory. + +- Merged the NX changes: + + - From dix/extension.c to NXextension.c. + - From dix/dixfonts.c to NXdixfonts.c. + - From dix/glyphcurs.c to NXglyphcurs.c. + +- Export of CARDINAL properties are expanded to 64 bit units on 64 + bit machines. + +- Solved a segmentation fault when handling configure notify events + in rootless mode on 64 bit machines. + +- Merged the NX changes from dix/property in X/NXproperty.c. + +- Correctly allocated the local variable used in the call to NXGet- + CollectedInputFocus to be of 64 bit on 64 bit machine. + +- Defined symbolic constants XlibWindow in order to propertly handle + export property on 64 bit machine. + +- Moved the XlibAtom define from Atoms.h to Agent.h. + +- Modified export properties of type Window and Atom in order to han- + dle correctly Window and Atom types on 64 bit machines. + +- Removed some invalid read in Atom handling code when compiled for 64 + bit, due to mismatched size of Atom type between Xlib and Xserver + code. + +- Modified some header files in order to properly see the correct pro- + totypes of some Xlib structures on 64 bit machines. + +- The variable currentDispatch is always defined. + +- The dispatch current time is updated, this way the initial timeout + can elapse and the splash window is removed. + +nxagent-1.6.0-10 + +- Imported changes from nxagent-1.5.0-103. + +- Removed some redundant redeclarations. + +- Merged the NX changes from randr/randr.c to NXrandr.c. + +- Removed some warnings in NXrandr.c. + +- Removed NXAGENT_FORCEBACK and NXAGENT_INTERNALBS code. + +- Added ddxInitGlobals function in order to compile with the new X.org + tree. + +- Converted nxagentSynchronizeShmPixmap from macro to function to + solve a graphical render problem caused by the variable's scope. + +nxagent-1.6.0-9 + +- Imported changes from nxagent-1.5.0-102 + +- Fixed TR10C01124. Function nxagentSetPictureFilter() filled the log + with a debug message. + +- Removed a debug message in Events.c. + +- Run function nxagentSetTopLevelEventMask() only in rootless mode. + +- In the Java application IntelliJ the dropdown menus was shown in a + wrong position when the main window was moved or minimized. The + problem is solved for KDE desktop environment. + +- Fixed TR08C00967, TR08C00969, TR08C00941. Our incomplete implementa- + tion of the MIT-SHM X11 extension was a problem for some applica- + tions using the Shared Memory Pixmaps. Now the extension support has + been completed, so the nxagent can handle the Shared Memory Pixmaps + requests. Introduced some changes in the render implementation to + synchronize the content of the Shared Memory Pixmaps with the X ser- + ver before performing the ChangePicture and Composite operations. + +nxagent-1.6.0-8 + +- Fixed TR09C01028. The problem was the GC foreground was not updated + on the X server. This was due to the private fields was not copied + from a GC to another in the function nxagentCopyGC(). Added macro + nxagentCopyGCPriv in GC.h. + +- Solved TR11C01162. Removed the dialog shown by nxcomp/nxagent when + the resume of a session is happening over a slow link. + +nxagent-1.6.0-7 + +- Imported changes up to nxagent-1.5.0-100. + +- Fixed some compilation errors. + +- Fixed a typo in nxagentChangeClip() declaration. + +- Fixed TR10C01040. After the session resume the applications using + OpenGL were not correctly resumed because some GCs were not recon- + nected. Now we save these GCs in a safe vector, so we can't lose + them. + +- Improved font reconnection procedure in order to take advantage of + new font channel provided by nxcomp. If resuming session fails be- + cause missing fonts, the font channel provided by nxcomp is added + to font paths of X server. After reconnection succeded the font + channel is removed from font paths. + +- In the Java application IntelliJ the dropdown menus remained opened + and shown in a wrong position when the main window was moved or + minimized. This problem has been solved by sending a sinthetic event + to client. This solves partially TR09C01012. + +- In the same application the caret was not shown in the text window. + Solved the problem by setting nxagentGCTrap before calling a MI + function in every GC operations. + +- Merged the NX changes: + + - From render/glyph.c to NXglyph.c. + - From Xext/shm.c to NXshm.c. + - From render/render.c to NXrender.c. + - From mi/miwindow.c to NXmiwindow.c + - From render/glyphstr.h to NXglyphstr.h. + - From render/picturestr.h to NXpicturestr.h. + - From render/picture.c to NXpicture.c. + - From dix/dispatch.c to NXdispatch.c. + - From dix/events.c to NXevents.c. + +- Changed picturestr.h glyphstr.h to remove some formatting changes + compared to the original files. + +- Disabled Xinerama extension in order to fix a type conflict in NX- + dispatch.c. + +- The current directory has been moved in front of the include dire- + ctory list. + +- Removed NXAGENT_FORCEBACK code in files imported from DIX. + +- Changed NXshm.c NXrandr.c NXproperty.c NXpicture.c NXglyphcurs.c + NXglyph.c NXextension.c NXrender.c NXdixfonts.c NXdispatch.c NXmi- + window.c to remove some formatting changes compared to the original + files. + +- Added copyright notice to file NXrandr.c. + +- All files, except those from mi and dix, compile fine in the new + tree. Problems remain with different size of Atoms and other XID + objects. + +- More compilation fixes for the new tree. + +- Merged the NX changes from dix/window.c to NXwindow.c. + +- Changed NXwindow.c and NXevents.c to remove some formatting chan- + ges compared to the original files. + +- More compilation fixes aimed at porting the agent to the new tree. + +- Started porting the agent to the 6.8.99.16 X.org tree. + +- Lot of compilation fixes aimed at building in the new environment. + +- Files imported from the X.org tree's dix and mi will have to be + recreated in the nxagent/X directory. The new files will be inclu- + ded and built from the nxagent/X director if the NXAGENT_UPGRADE + symbol is defined (as it is the case when building in the 2.0.0 + nx-X11 tree), otherwise the usual NX* files in the nxagent's dir- + ectory will be compiled. + +- Fixed TR09C01021. SIGHUP it was not received from the proxy. The + handler of SIGHUP must be installed also in the case of not persi- + stent sessions. + +- In non persistent case: if session is normally running, SIGHUP sig- + nal is dealt like SIGTERM, otherwise it is passed to the proxy. + +- Fixed TR09C01027. Changed function nxagentHandleConfigureNotify() + in order to get changes of the staking order in a rootless session + even if no window manager is running. + +- Fixed TR09C01025. The problem was XView application could be unable + to respond to user's input. Modified the Event Mask for non top le- + vel windows reparented by the root window. Set the input member of + XWMHints to communicate the window manager the keyboard focus model + used by the application. + +- Fixed TR09C01026. Added 'fast' and 'slow' to the set of accepted + command line parameters. 'fast', 'slow' and 'geometry' command line + parameters have precedence regarding the options file. + +- Fixed TR08C00968. There was a problem in the implementation of the + render extension. + +- Fixed TR09C01016. In rootless mode when the session was resumed, + the cursor was shown with a wrong shape. + +- Fixed TR09C01011. Allowed clients to monitor the root window for + structure redirect, button press and resize redirect events in root- + less mode. This is a quick hack to make the java bean shell work + flawlessy with the agent. + +- Solved TR08C00961. Improved the algorithm updating the sprite win- + dow. Now it is updated based upon crossing and motion event. Since + on some X server, like Windows and MacOsX X servers, the only cros- + sing event is not a reliable method to trace the sprite window chan- + ges. + +- Fixed TR08C00966. Solved the problem on Windows when a rootless + session is suspended and some of the application windows are + minimized. + +- Fixed TR08C00960. Updated the internal screen dimension in rootless + sessions at reconnection. + +- Fixed TR09C01005. The problem was that the 'render' option on the + command line was overridden by the one provided in the options file. + +- Implemented the HandleEmptySplitEvent function that synchronizes all + the drawables after the depletion of the split store, when the lazy + option is activated. + +- Some changes in order to avoid duplicated refreshes when display- + ing Mandrake's kde menu. + +- Changed level of some logs from WARNING into TEST in Window.c and + in Rootless.c. + +- Fixed TR08C00958. Changed the log message printed when the user re- + quest to resume the session. + +nxagent-1.6.0-6 + +- When reconnecting, try to estimate the shift on the main window due + to WM reparenting. + +- In the handling of configure events, if a WM is running save the po- + sition of the main window only if event is synthetic. + +nxagent-1.6.0-5 + +- Command line option -noshmem disables shared memory extension in the + agent. + +- Changed level of some logs from WARNING into TEST. + +nxagent-1.6.0-4 + +- Some changes in order to improve handling of expose events in root- + less. The GetInputFocus request is not sent after reconfiguring a + top level window: window manager intervention could give race condi- + tions. The request is placed in WindowsRestructured() in order to be + sure it is sent after any event that could generate expose. + +- Zero lenght change property are now imported in rootless mode. + +- Corrected few typos. + +- Replaced the function usleep with NXTransContinue when NX transport + is running. + +- Changed the session state to GOING_DOWN as soon as the reconnection + is failed. + +nxagent-1.6.0-3 + +- Updated rootless toplevel window map when a window is reparented to + the root window. + +- Renoved duplicated entry in rootless toplevel window map. + +nxagent-1.6.0-2 + +- Removed TEST and DEBUG in Color.c. + +- Removed a compilation error in Atoms.c if DEBUG is enabled. + +- Removed invalid read at server reset in rootless mode, now the a- + toms description are duplicate before that we cache them. + +- Now the local atom in the atom cache are reset when exiting from + the dispatch loop. + +nxagent-1.6.0-1 + +- Opened the 1.6.0 branch based on nxagent-1.5.0-87. + +nxagent-1.5.0-87 + +- Corrected the enable-disable lazy encoding dialog in order to show + the correct keystroke Ctrl-Alt-E. + +nxagent-1.5.0-86 + +- Reset agent position at reconnection when the new size of display + doesn't match the old size and fullscreen is on. + +- Inserted a comment about handling of expose events. + +nxagent-1.5.0-85 + +- If fullscreen and resize options are true when reconnecting, geo- + metry option is ignored and the root window is resized to the en- + tire screen. + +- Read the position of the main window at startup from geometry op- + tions. + +nxagent-1.5.0-84 + +- Changed the keystroke Ctrl-Alt-L to toggle the image encoding on + and off to the new combination Ctrl-Alt-E. + +- Enabled the keystroke Ctrl-Alt-M to minimize the root window also + in window mode. + +nxagent-1.5.0-83 + +- Replaced the call to XIfEvent() with something less efficient but + safer, based on XCheckIfEvent(). The previous version might never + return if an I/O Error was encountered waiting for the event. The + new version fails gracefully, and returns after having restarted + the client. + +nxagent-1.5.0-82 + +- Removed some debug logs. + +nxagent-1.5.0-81 + +- Forced window mode if X server geometry has changed at reconnection. + +nxagent-1.5.0-80 + +- Reset resize desktop at startup flag before reconnection. + +nxagent-1.5.0-79 + +- Removed race condition in the parsing order of the options parame- + ter, now the geometry parameters are set in screen initialization. + +nxagent-1.5.0-78 + +- Disabled auto-resize and viewport mode dialog in case of rootless + session. + +- Removed no more used -backingstore option from usage messages. + +- Modified -bs command line option: now the default value "when_re- + quested" is always set. + +- Fixed wrong size of root window when switching from full screen to + window mode and viewport navigation mode is enabled. + +- Added option that solved a minimize bug in LeaveNotify when the + root window is in full screen and the user is using viewport navi- + gation mode. + +- Forwarded HUP signal to NX transport, when session state is up and + running. + +nxagent-1.5.0-77 + +- Do PutImage in every case. Don't check if the drawable is synchro- + nized. + +- Do CopyArea, CopyPlane, Composite in every case, don't check whether + the source is dirty. + +nxagent-1.5.0-76 + +- Terminate rootless session 15 seconds after the last mapped window + has been destroyed. + +nxagent-1.5.0-75 + +- Ctrl-Alt-T shows suspend/terminate dialog also in rootless mode. + +- Sleeps 50 ms in the block handler if the session state is down. + +- In rootless mode, the focus window is changed following FocusIn + events received from the real X server, also in the case no win- + dow manager has been detected. + +nxagent-1.5.0-74 + +- Changed the alerts names to comply with nxcomp-1.5.0-57. + +- Moved loading of placeholder from startup to the first time it is + needed. + +- Corrected a typo in the CHANGELOG. + +nxagent-1.5.0-73 + +- Ignored put image on not synchronized drawables, when the image + doesn't cover the entire surface. + +- Added parsing of render parameter in option file. + +- Ignored I/O Error when session is suspended. + +- Managed I/O Error at reconnection. + +nxagent-1.5.0-72 + +- Fixed offset of the default window at reconnection and after switch- + ing from fullscreen in window mode. + +- Suppressed the -lazy command line option. + +- Made some slightly changes in GCOps.c and Pixmap.c in order to com- + ply with the new 'Lazy' option. + +- Avoided to do CopyArea, CopyPlane and Composite operations when the + source drawable is dirty. + +- Rootless disconnect dialog has changed. This dialog is launched + after some time the last window has been closed. + +- Ignored geometry changes at reconnection if resize at startup is + not set. + +- Removed reset of the offset of the root window in viewport mode at + reconnection. + +- Fixed some refreshes problems in viewport mode and in desktop resize + mode. + +- Fixed a memory leak in nxagentWindowExposures(). + +- Added predicate to nxagentDispatchEvents. + +- Implemented framework in order to wait for a free resource entry, + when calling the asynchronous Collect* functions. + +nxagent-1.5.0-71 + +- Added keystroke Ctrl+Alt+L switching lazy encoding option. + +- Disabled viewport movement in resize mode. + +- Changed agent geometry at screen resize. + +- Changed agent geometry at initialization. + +nxagent-1.5.0-70 + +- Restored the set of blocked signal after the dialog pid just laun- + ched has been stored. + +- Removed an already fixed FIXME. + +- Updated the copyright message. + +nxagent-1.5.0-69 + +- Started working at the integration of the lazy encoding functiona- + lity. Made the agent draw the placeholder if the image is split and + never suspend the client. There is no provision for synchronizing + the drawables yet. + +- Made the lazy encoding configurable by the new 'Lazy' option. + +- Updated to include the changes in the NXStartSplit() and NXCommit- + Split() requests. + +- This version requires nxcomp-1.5.0-55 and nxcompext-1.5.0-16. + +nxagent-1.5.0-68 + +- Fixed reconnection of iconified windows. + +- Ignored the X server's scratch pixmap at reconnection. + +- The desktop gets automatically resized at reconnection if the desk- + top resize option is enabled. + +- Added the resize option in nxagentProcessOptionsFile() to allow the + user to change the geometry of both the root and the default window + at reconnection. + +- Fixed max size of the default window at startup when auto-resize + mode is enabled or in the case of a reconnected session. + +- Made some minimal changes in Atoms.c and NXdispatch.c. + +nxagent-1.5.0-67 + +- Changed handling of expose events received from real X server. A re- + gion is composed from expose events by checking the count field. + +- Reimplemented the exposures managing. Now the GetInputFocus request + is sent after a window has been configured or unmapped. We use a + vector to store windows originating expose events while waiting for + the reply to GetInputFocus. + +nxagent-1.5.0-66 + +- Added the DisplayLatency value in the agent options. This is int- + ended to give a hint about the latency of the current display + connection. The value is currently used to determine if the agent + is running across a slow link, and so it's appropriate to display + the begin-reconnection alert. + +nxagent-1.5.0-65 + +- Added the DesktopResize option. It controls the behaviour of the + automatic (RandR) resize of the desktop when dragging the agent's + window border. + +- Automatic resize is again the default. + +- Disabled the test logs in Events.c, GCOps.c Pixmap.c, Handlers.c, + Reconnect.c. + +- More cosmetic changes and code cleanup. + +nxagent-1.5.0-64 + +- Rewritten the image streaming procedure to better leverage the new + infrastructure. The start-split/end-split procedure is always init- + iated by the agent, including when the size of the image is below + the threshold, but the client is only suspended when the split has + taken place in the NX transport. + +nxagent-1.5.0-63 + +- Updated image streaming to use the new NX notification events. + +- Removed the references to the NXSync() operation, not used anymore + by the agent. + +nxagent-1.5.0-62 + +- Fixed wrong position of the root window in case of viewport naviga- + tion mode. + +- Added a field to the client private to trace the client type. + +- Tracked which clients are nxclient dialogs in order to not run the + pulldown dialog on them. + +nxagent-1.5.0-61 + +- Disabled server reset if not needed by XDMCP. + +- Disabled persistence for indirect XDMCP session until the first gre- + eter with the list of host has disappeared. + +- Created a small data structure to contain information about integri- + ty status and placeholder status of a drawable. + +- Modified the call to nxagentRealizeOnePixmap function in order to + avoid errors during the signal handling. + +nxagent-1.5.0-60 + +- Added the XDMCP option. If both Rootless and XDMCP are selected the + session will fail. + +nxagent-1.5.0-59 + +- Limited the permission to reset the agent only to indirect XDMCP + sessions, only one reset is allowed. + +- Fixed max size of the default window when switching from fullscreen + to window mode and auto-resize is disabled. + +nxagent-1.5.0-58 + +- Enabled reset mechanism, in order to make XDMCP session work proper- + ly. + +- Added XSync for window manager detection, after a server reset since + the XInternAtom already used should be cached. + +- Now the pixmap status is always tested on real pixmap. + +- The placeholder is drawn only once per drawable. + +- Implemented nxagentUnmapWindows() in case of failed reconnection if + the session was running in fullscreen mode and NX transport is not + enabled. + +- In nxagentPutSplitImage(), passing leftPad to XCreateImage(). + +- This version avoids sending the XSync() to the remote when a large + amounts of GetInputFocus requests are issued by the same client. + It will require more testing, especially to verify how it works on + old Windows machines. + +- Changed the NXCommitSplit() call to comply with the new interface. + +- The drawable status is now propagated on graphic operations where + the source is using the tile and stipple components on the graphic + context and the tile or stipple are not synchronized. This affects + the following operations: + + - PolyLines + - PolySegment + - PolyRectangle + - PolyArc + - FillPolygon + - PolyFillRect + - PolyFillArc + - PolyText8 + - PolyText16 + +nxagent-1.5.0-57 + +- Removed two XSync() operations at screen initialization. + +- Modified keyboard initialization in order to load the correct rules. + This is choosen according to the vendor string of X-Window system in- + stalled on the local machine. + +- Corrected a few typos. + +- When the NX transport is present, the failed reconnection dialog is + launched on the remote X server by using the NXTransAlert() function. + The same dialog is managed by NXTransDialog() when a session is run + by connecting directly to the display. + +- Removed the function nxagentUnmapAllWindows(). + +nxagent-1.5.0-56 + +- Set the parent window for the pulldown dialog. + +nxagent-1.5.0-55 + +- Added an alert at the time the reconnection procedure begins. The + alert is shown only when the NX transport is present and the link + type is not LAN and is removed at the end of the resume operation. + +- Removed the former code used for testing the alert functionality. + +- Moved the function removing the splash window in Splash.c. + +nxagent-1.5.0-54 + +- Fixed initialization of window privates storing exposed regions. + This solves a bug affecting the refresh of windows introduced in + nxagent-1.5.0-42. + +- Added a STARTING state to nxagent. Until the agent is in this state + the suspension mechanism is not activated. + +nxagent-1.5.0-53 + +- Added the special keystroke Ctrl+Alt+R to enable or disable the + auto-resize mode. + +- A dialog notifies the user when the auto-resize mode is toggled. + +- Added a test alert at startup, to verify that NXTransAlert() is + working as expected. + +nxagent-1.5.0-52 + +- Changed the code to call NXTransDialog() and NXTransExit(). + +nxagent-1.5.0-51 + +- Solved a bug that prevented the clients that had been restarted + to be immediately selected for input. + +- Removed some code that was added for debugging. + +nxagent-1.5.0-50 + +- Fixed a memory leak in nxagentHandleExposeEvent(). + +- Fixed a memory leak in nxagentDestroyWindow(). + +- Now rootless dialog is launched only when last mapped window is + deleted, since we have pulldown window to control the session. + +- Added pulldown dialog to handle NX windows in rootless sessions. + This dialog is activated from a "magic" slice of window under the + top border. + +- Solved a problem with sessions that might fail at reconnection. + +- Now the message text of the dialog launched in case of failed re- + connection explains the reason why the agent cannot be resumed. + +- Implemented function nxagentUnmapAllWindows() to unmap all windows + if nxagent has failed to migrate the session to the new display. + +nxagent-1.5.0-49 + +- Fixed the problems with propagation of the drawable status. + +- Modified nxagentPutSplitImage in order to set the correct height + of the last split image. + +- Code cleaning and optimization in Dialog.c. + +- Solved bug that switched on the full screen state in rootless se- + ssion. + +- Changed the way dialog caption are set in rootless mode. It is set + upon the session name or session id value. + +- Corrected the function nxagentFailedReconnectinDialog(). + +nxagent-1.5.0-48 + +- Solved bug that switched on the full screen state in rootless se- + ssion. + +- Changed the way dialog caption are set in rootless mode. It is set + upon the session name or session id value. + +- Corrected the function nxagentFailedReconnectinDialog(). + +nxagent-1.5.0-47 + +- Now we call NXContinueOnDisplayError() with value 1 just after + having opened the display. This will cause the NX Xlib to return + in the case of an I/O error, instead of quitting the application. + +- Removed the references to Context.h and the related elements. + +- Reflected the changes occurred in NXlib.c regarding NXDisplayErr- + ror() and inverted the logic compared to NXDisplayIsValid(). + +- Added a dialog box to notify the user when nxagent has failed to + migrate the session to the new display. Because the main X agent + connection is unavailable, this dialog uses the auxiliary nxcomp + keyboard channel. + +- Disabled the special keystroke Ctrl+Alt+S if any dialog is already + running. + +- Started implementing lazy synchronization of pixmaps. At the pre- + sent moment the implementation doesn't try to perform any optimi- + zation on the windows' regions that have to be redrawn and neither + it checks the congestion state. After having synchronized a reaso- + nable number of pixmaps, it simply sends to all the affected win- + dows an expose event, mandating the repaint of the whole area. + +- Removed a warning in Atoms.c. + +nxagent-1.5.0-46 + +- Removed the longjmp() at the time an I/O error was encountered on + the display. + +nxagent-1.5.0-45 + +- Removed UNDEFINED status for drawables. + +- Now lazy encoding affects only windows. + +- Changed the block handler to call NXTransFlush() with 'if needed'. + +nxagent-1.5.0-44 + +- After reconnection, stored exposed regions are reset and the manag- + ing of duplicate expose events is restarted. + +- Detection of window manager has been moved to the start of screen + initialization. Screen dimensions and fullscreen option are over- + ridden if no window manager is detected. + +- Added a call to XSync() in switching fullscreen function in order + to synchronize it with the network behaviour. + +- Started adding provision for deferred writes in the NX transport. + When the flush policy will be set accordingly, X data accumulated + by the proxy will be written to the network under the control of + the block and wakeup handlers. + +- Fixed a bug in nxagentCopyArea(). In some cases, pixmap drawables + was erroneusly supposed to be windows. This produced invalid reads + when trying to access to fields of WindowRec structure. + +nxagent-1.5.0-43 + +- In the code managing the property notify events, NXCollectProperty + is not called if the window is not found in the tree mantained by + the agent. + +- Changed managing of screen resize in order to avoid repeated resize + of desktop. The agent sleeps one second, then all configure event + are read from the queue and the server connection. The desktop re- + size is performed after the last read configure event. + +- Changed nxagentImportProperty() in order to use NXCollectProperty + instead of XGetWindowProperty. This avoids many round-trips in root- + less mode. + +- Fixed Invalid write problem in nxagentRRSetScreenConfig(). + +nxagent-1.5.0-42 + +- Modyfied test of NXSetUnpackGeometry for visuals, so now the compa- + rison between visuals is based on their IDs and not on the memory + area allocated for their visual structure. + +- Modified exposure managing in order to avoid duplicated refreshes. + Now only exposed regions not formerly managed yet are sent to the + clients. + +nxagent-1.5.0-41 + +- Modified nxagentCloseScreen() in order to free the frame buffer. + +- Added information of the integrity of the windows. Now the integrity + has became a drawable property that will expand in every drawable to + drawable operation. + +nxagent-1.5.0-40 + +- Splitting of images now happens only if the display is a valid con- + nection. + +- The isItTimeToYield flag is now set in the dispatcher only when the + client has been actually suspended because of a karma, a sync, or + a split operation. + +nxagent-1.5.0-39 + +- Improved the handling of the PutImage request to offer provision + for splitting images coming from orders generated by extensions. + +- Fixed a problem with clients being unexpectedly restarted instead + of waiting for the end of split. + +nxagent-1.5.0-38 + +- Added a persistent dialog when agent is running in rootless mode. + +- Modified the policy of management of nxclient dialogs. + +- Fixed memory leak problem in nxagentPutSplitImage(). + +- Modified printing of some debug messages to avoid passing a null + pointer to fprintf(). + +nxagent-1.5.0-37 + +- Implemented initial support for streaming the packed images in the + handling of the MIT-SHM extension. + +nxagent-1.5.0-36 + +- Updated the pixmap status when a placeholder is copied on the pix- + map and when the pixmap is the target of a RENDER composite opera- + tion. + +- Solved the TR05C00900. The NX transport was forced to be set when- + ever the display name contained the nx prefix. + +- Implemented the FRSA052393. Removed the compression filters applied + by nxagent to cursor pixmaps. + +- Modified RANDR implementation to make the user able to resize the + desktop by simply dragging the agent window's border. Screen resize + is made after a small timeout, to give time to the last configure + event to come from the server and avoid multiple re-configurations + of the screen. + +nxagent-1.5.0-35 + +- Added the current screen size to the set of sizes returned by the + RANDR extension. + +nxagent-1.5.0-34 + +- Corrected the placeholder xpm image. + +- Added a client dialog to notify the user that nxagent is running in + fast or in slow mode after pressing Ctrl + Alt + S. + +- Modified RANDR implementation to give a set of screen sizes. Im- + plemented functions actually performing screen resize on a RANDR + request. Now toggling to fullscreen make the desktop cover the en- + tire screen area. + +nxagent-1.5.0-33 + +- Added an auto-disconnect feature similar to the one present in the + Windows Terminal Server. The feature is modeled on the built-in X + server's screen-saver. If the agent doesn't receive any input from + the user in a given timeout, it will either terminate the session, + if no client is connected to the display, or will suspend it, so + that applications will be left running. + +- The default is to disable the auto-disconnect option. The feature + is activated by specifying a "-timeout s" parameter on the command + line, with s being the timeout in seconds. The minimum allowed ti- + meout is 60 seconds. + +- The waitpid() call now only checks the agent's own children. + +- Moved the longjmp() context declaration to a new Context.h file to + avoid clash with redefinitions by the PNG headers. + +- Few other cosmetic changes. + +nxagent-1.5.0-32 + +- Added a check on the type of the connection to avoid cleaning the + images when not needed. + +nxagent-1.5.0-31 + +- Modified the placeholder frames, now it has a left top black border + and a bottom right grey one. + +- Modified fbShmPutImage() in order to set the correct size for the + temporary pixmap. + +- Modified nxagentForceExposure() and nxagentHandleExposeEvent() in + order to clip exposed regions to the window size region of the root + window. + +- Added a new placeholder xpm image. + +- Corrected few typos. + +- Added function to synchronize GC tiles and stipples whenever those + pixmaps have been realized. + +nxagent-1.5.0-30 + +- Hidden viewport windows to clients in QueryTree request in order + to make work XDMCP properly. + +nxagent-1.5.0-29 + +- Removed some warnings with gcc 3.4. + +- Added desktop -D switch to usage. + +- Paint window background draw on framebuffer only with OpenOffice + client. + +- Now fast copy are and fast getimage are no more set according to + the link type, their default value has been set to true. + +nxagent-1.5.0-28 + +- Modified nxagentUpdateViewportFrame() in order to solve a refresh + problem. Windows composing the external frame must be always on top + to be sure that agent sends expose events for every window. + +- In rootless mode agent doesn't export anymore the properties when + disconnected from the X server. + +- Changed the way agent check if the connection with the X server + is available. Instead of using a state machine it uses the display + flag. + +- Removed the SIGTERM handling function in persistent code. We don't + need anymore those function since agent is no more sleeping when + disconnected. + +- Implemented nxagentFreePropertyList() function in order to empty the + list of exported properties when the rootless agent is disconnected. + +- Added special keystroke Ctrl + Alt + S toggling between fast and + slow mode for GetImage and CopyArea. + +- Added missing handling of down arrow key in Keystroke.c. + +- Modified nxagentForceExposure() in order to intersect exposed re- + gions with the clip region of the root window. This prevents window + functions from painting outside the frame buffer. + +- Added the field usesFrameBuffer in struct nxagentPrivClient. Modifi- + ed GC funtion and DoGetImage() in order to write in the frame buffer + only if usesFrameBuffer is True. + +- Removed code performing PutImage in the frame buffer, as it is use- + less at the moment. + +- Modified ProcChangeProperty() to check WM_NAME property. + +- Added a piece of code in nxagentOpenScreen() checking for and remo- + ving duplicated visuals. + +- Added the Dialog.c Dialog.h files. Unified all calls to NXDialog, + and blocked SIGCHLD before calling in order not to get the signal + before the child pid has been stored. + +- Modified the algorithm that disconnect the running session in + order to avoid the opening of a new dialog box for closing or + suspending the nxagent. + +nxagent-1.5.0-27 + +- Changed the disconnect/reconnect procedure in order to have a pro- + per default colormap vector when session is suspended, solving a + segmentation fault in create window function. + +- Corrected few errors in slow copy area mechanism. + +- Modified screen initialization in order to allocate memory for the + internal frame buffer. + +- Modified some GC functions for writing to and reading from the frame + buffer. + +- Modified nxagentCreateWindow() for initializing the window in the + frame buffer. + +- Modified nxagentCreateColormap() in order to use the default visual + if a matching one is not found. + +- Modified function DoGetImage() in order to call nxagentGetImage() in + place of nxagentGetDefaultImage() if fast option is on. + +- Added nxagentCheckWindowIntegrity() function verifying the matching + between the internal frame buffer and the X server for a window. + +nxagent-1.5.0-26 + +- Added the property "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR" to the list + of exported property in rootless mode, in order to let clients use + the system tray. + +- Modified import of WM_STATE properties in rootless mode in order + to better handle null resources. + +- Enhanced the slow CopyArea mechanism in case of one part of the + image is out of the X server screen or out of nxagent screen. + +- Changed type for variables width and height of default window + from 'unsigned int' to 'int'. + +nxagent-1.5.0-25 + +- Added a new signal handler for SIGCHLD. The transport is set to + forward the signal (by means of a new NX_SIGNAL_FORWARD action). + This allows the agent to wait for its own children. + +nxagent-1.5.0-24 + +- Set up the RANDR extension. When querying the configuration, the + clients get 3 sizes, the first being the current size, the second + being the maximum size of the remote display, the third being the + minimum size (arbitrarily set to 100x100 pixels). Screen sizes in + millimeters are calculated based on the size reported for the real + display. + + An example of xrandr -q output is below: + + SZ: Pixels Physical Refresh + *0 800 x 600 ( 270mm x 203mm ) + 1 100 x 100 ( 33mm x 33mm ) + 2 1400 x 1050 ( 474mm x 356mm ) + Current rotation - normal + Current reflection - none + Rotations possible - normal + Reflections possible - none + + As you can note, reflections and rotation is not possible. + +- Set up the GLX extension. This provides basic support with GLX op- + erations being translated into core X protocol primitives. + +- Moved initialization of GLX and RANDR to the Extensions.c file. + +- Removed the references to the unused mfb library. Modified Screen.c + to allocate the right privates for the fb code. + +- Modified the Xserver Imakefile to link nxagent with FbPostFbLibs + and avoid including mfb/libmfb.a. + +nxagent-1.5.0-23 + +- Fixed an incorrect buffer length calculation when retrieving a re- + mote property. + +- Added a check to avoid the use of a NULL pointer when changing the + window cursor. + +- Implemented a function to lookup the remote pixmaps. + +- Changed the RENDER initialization messages. + +- Corrected a few typos in symbol names. + +nxagent-1.5.0-22 + +- Added the nxagentNeedConnectionChange() macro. + +- Small optimizations in the block and wakeup handlers. + +nxagent-1.5.0-21 + +- NXCollectGrabPointer() is called by passing nxagentDefaultClient(). + This is a macro that checks the validity of requestingClient and, + if the pointer is NULL, defaults to NXNumberOfConnections - 1. + +nxagent-1.5.0-20 + +- Replaced all calls to XGrabPointer with the asynchronous version + provided by nxcompext. + +- In DeactivatePointerGrab() function, mouse button state is set to + up if the window entered by the pointer is the root window and the + agent is in rootless mode. This change is needed because the sub- + sequent KeyRelease event could be not received by the agent (for + example if the focus had left the window), so that agent could be + unable to update the mouse button state. + +- In rootless mode, grabs exported to X in ActivatePointerGrab() are + always made asynchronous. The synchronous behaviour is implemented + by the agent, so that requiring a further synchronous grab down to + the real X server is of little use and potentially harmful. + +- Modified function XYToWindow() in order to manage the case that + mouse pointer is located on the title bar of a top level window in + rootless mode. + +- Reflected name changes to NXImageCache variables. + +nxagent-1.5.0-19 + +- Changed the implementation of the SIGHUP handler to forward the sig- + nal to the proxy only when appropriate. This allows nxagent to close + the NX connection without having to go through an I/O error on the + display. + +- Modified nxagentBreakXConnection() to check if the NX transport is + running and thus use NXTransDestroy(). Using a simple shutdown() may + not work, for example if NX is using the memory to memory transport. + +- Added the -D option, to let users specify that agent must be run in + desktop mode. This is presently the default. + +nxagent-1.5.0-18 + +- Set the PropertyChange mask on input/output window in rootless mode + in order to get the PropertyNotify events. + +nxagent-1.5.0-17 + +- Cleaned of the reconnection routines, removed the NXAGENT_RECONNECT + macro. + +- Now the SIGHUP handler forwards the signal also to the NX transport. + +- Moved the NXTransDestroy() call in the closure of the display, so + we can avoid going through the I/O error handler. + +- Removed an invalid free in the function that closes the display. + +- Commented out more code in Display.c to avoid the segfault on exit. + +- In rootless mode, now function XYToWindow() starts search from the + last window originated an EnterNotify event. In this way, we can + prevent shaded windows from getting mouse events. + +- The variable to disable the smart scheduler is set at its definition + instead of setting it in the Dispatch function. This avoids the call + to SmartScheduleInit. + +- Changed implementation of cursor visualization in rootless mode. We + made the cursor attributes changes go transparently to the X server + while in desktop mode we ignore any client request to change the cu- + rsor on the X side, and we just set the cursor on the default window + any time the pointer cross a window border. + +- Expanded the range of properties exported on the remote Xserver, + this way we export properties whose atom name starts with "WM_" and + "_NET_". + +- In Rootless mode PropertyChangeMask is added to top level window in + order to get PropertyNotify Events. + +- First implementation in rootless mode of nxagentImportProperty fun- + ction with which after reception of PropertyNotify Events, all chan- + ging properties coming from external clients such as Window Manager + will be imported in agent windows. + +- Changed the GetEventMask function in order to handle the InputOnly + windows that need to be notified of property changes in rootless + mode. + +nxagent-1.5.0-16 + +- Implemented the -B command line switch, to let nxagent impersonate + a "pure" proxy on the NX server side (that is without X connections + having to be managed by the nxagent's dispatcher). Such a "nxagent + -B" is going to replace the corresponding nxproxy process that in + previous version of NX server was run with the same options. + +- When running nxagent in 'bind' mode the X port where the the proxy + has to listen for connection must be specified after the -B option. + The other NX options must be passed in the DISPLAY environment. + + Example: + + nxagent -B :9 + +- The initialization procedure will check that the display included + on the command line matches the one specified in the NX display + options. + + For example, given the command: + + nxagent -B :9 + + The NX options must be something like: + + DISPLAY=nx/nx,link=modem:9 + + This allows users to find out which display the agent is impersona- + ting by running a 'ps' and inspecting the command line. + +- Fixed a bug preventing the proxy's ClientMessage to reach the right + function when activating rootless mode. + +- Removed unused function nomachineLogo. + +- Code cleaning and soem optimizations in Rootless.c. + +- We want to import all properties changed by external clients to our + internal windows. But we must ignore property notify generated by + our own requests. For this purpose we implement a list to record + every change property that we dispatch. This way when processing + a property notify we can distinguish between the notify generated + by our request and those generated by an 'outside client'. + +- In rootless mode, optimized window configurations mantaining inter- + nal stacking order. + +- Fixed focus troubles in rootless mode. Now focus window is set fol- + lowing FocusIn events. + +- In rootless mode, now fake KeyRelease events on FocusOut are sent + only if keys having down state are modifiers. This prevents from + sending key events to a wrong client. + +- Removed unused function nxagentRootlessNextSibling in Rootless.c. + +- Removed unused function nxagentRootlessStackingOrder in Rootless.c. + +- Fixed compilation error if TEST log is enabled in Events.c. + +- Changed Options variables to comply with NX naming rules. + +- Some additional cosmetic changes. + +nxagent-1.5.0-15 + +- Modified functions nxagentPutImage and DoGetImage for XYPixmap fo- + rmat. + +- Completed implementation of shared memory extension. + +- Implemented a mechanism that prevents monitoring of SubStructure- + Redirect ResizeRedirect and ButtonPress events by any clients simu- + lating the presence of a window manager running inside the agent. + +- Added debug functions in order to check the status of syncroniza- + tion between the pixmaps residing on the X server and the local + framebuffer ones. + +- Changed the policy used when realizing all the pixmaps in 'lazy en- + coding' mode so that the agent now switches to 'eager' policy. + +- Fixed the routine handling the pixmaps realization: pixmaps with + an invalid id are not processed anymore. + +- Solved a bug in the routine taking care of clearing the NoMachine + logo: the state of the background was set to 'pixel' without de- + stroying an eventual backround pixmap. + +- Solved a bug in the 'MakeRootTile' function: the value returned by + 'AddResource' was not interpreted in the correct way causing the + function to bail out without drawing the NoMachine logo and set- + ting the background state to Pixmap. + +- Renamed PlaceHolder.c to Lazy.c and PlaceHolder.h to Lazy.h. + +- Inserted a test feature that cleans the framebuffer pixmaps when + they are created. + +nxagent-1.5.0-14 + +- Changed some reconnection messages. + +- Now the disconnect procedure is called also after an IO Error is + received. + +- The rootless agent now doesn't filter anymore keystrokes combina- + tion related to desktop feature, like viewport navigation the full- + screen state and minimization. + +- In rootless mode, internal stacking order is updated by comparing + the stack of top level windows mantained by the X server with the + one mantained by the agent. A global configuration of windows is + performed from top to bottom through the stack. + +- In rootless mode, map state of top level windows is kept up to date + by managing map and unmap events. + +- In rootless mode, enter events are managed to keep track of top + level window position. It is very useful for managing differences + among window manager behaviours. It should be reimplemented follo- + wing the advice given in ICCCM 4.1.5. + +- In rootless mode, requests of configure top level windows are di- + rectly forwarded to the real X server. Internal configuration is up- + dated when configure events are managed by the agent. In order to + mantain internal stacking order up to date, a query tree request is + performed on the real root window. + +- Added viewport navigation by Ctrl + Alt + keypad arrows. + +- Fixed wrong internal configuration of agent top level windows, while + agent runs in rootless mode with metacity window manager. + +- Fixed segmentation fault in nxagent running in rootless mode with + OpenOffice. + +- Fixed wrong internal stacking order of drop down menus of firefox + with nxagent in rootless mode. + +nxagent-1.5.0-13 + +- Fixed compilation problem on solaris. + +- Modified the modify pixmap header function. Previously this function + has been modified in order to solve a glyph problem, enlarging both + the pixmaps dimensions by four. Corrected the misbehaviour that + modify the pixmaps dimension even if the caller doesn't want to + change it. + +nxagent-1.5.0-12 + +- Fixed erroneous behaviour of Root Window in fullscreen mode caused by + wrong value of XSpan and YSpan. + +- Fixed wrong clients' position at Reconnection in Rootless mode, + setting offset and WinGravity fields in XsizeHints structure. + +- Fixed segmentation fault on closing windows that stay always on top. + +- Moved the handling of configure notify events in the appropriate + functions, and cleaned it. + +- In rootless mode, internal stacking order of top level windows is + mantained up to date by monitoring events from window manager top + level windows. + +- Modify the creation of screen at reconnection for detecting an + eventual failure. + +- Removed export of window properties on the X server in desktop mode. + +- Changed the events mask for client's window set on the X server. + We don't use anymore the window mask choosen by clients. In rootless + mode for a top level window we use the default event mask and for a + child only the exposure mask. + +nxagent-1.5.0-11 + +- Restored default event mask at reconnection. + +- Fixed abnormal behaviour in rootless mode if application windows are + close to the lower and right bounds of the screen. This trouble was + due to the wrong size of the agent root window. + +- Fixed abnormal behaviour in rootless mode for mouse button events if + the application window is not fully contained in the screen. + +- In rootless mode, exposed region are extended a few to take in ac- + count border width offsets caused by window managers. + +- In rootless mode, grab pointer requests from clients are forwarded + to X server. This makes application able to close their pop up win- + dows on a pointer event. + +- Fixed wrong position of the agent root window after resize of main + window. + +- Changed the size of viewport frame windows in order to avoid re- + freshing problems. + +nxagent-1.5.0-10 + +- Handled the Client messages on rootless mode. + +- Initializations of event masks have been moved in a unique group of + functions. + +- Disabled the SmartScheduler in dispatcher as it seems to affect the + responsiveness of nxagent. + +- Modified the block and wakeup handlers. We could have left data to + write to our display connection when entering in WaitForSomething() + so we now flush everything before entering the select() and let the + proxy do all the buffering. + +- Fixed the wakeup handler to match the correct prototype. + +- Few cosmetic changes. + +- Inserted a test feature that cleans the framebuffer pixmaps when + they are created. + +- Adjusted pixmap status information in almost every gc operations. + +- Removed a warning for usleep not defined on Suse 9.0. + +- Adjusted pixmap status information in copy plane operations. + +- Throwed fatal error if on lazy encoding the place holder pixmap + couldn't be loaded. + +- Removed the static path to xpm file in place holder initialization. + +- Removed useless signal handler initialization multiple times. + +- Refined validation of atoms in the atom cache code. + +- Corrected few errors in atom cache initialization. + +- Added a primitive atom cache that mantain the map between internal + and external atoms. + +- Window properties export began on the X server side in rootless + mode, this way nxagent open the communication between local clients + and the window manager on the X server. + +nxagent-1.5.0-9 + +- Fixed wrong position of the main window in case of maximizing in + window mode. + +- Set the correct scan line lenght for XYPixmap created in PutImage + and GetImage. + +- Removed a segmentation fault in GetDefaultImage. The problem arose + because the XYPixmap created with a data storage taking in account + of only some planes instead of all the depths planes. Despite XPut- + Pixel was treating the image as a complete XYPixmap of that depth. + +- Removed MapWindow Error at reconnection caused by wrong value of + IconWindow. + +- Now nxagent_WM_START is intialized as soon as the Atoms are + queried. + +- Removed Geometry restrictions. + +- Changed the configuration of the agent window in window mode. + +- The agent window is correctly reconnected even if is resized. + +nxagent-1.5.0-8 + +- Updated copyright notices. + +- Removed a segmentation fault in font cache cleaning routine. The + problem arise when the session is disconnected and the font struct + are not allocated. + +- Used the return mask of XParseGeometry to correctly set only the + parameters that are involved. + +- Unified the initialization of all the geometry related parameters. + +- Updated the offset of the four viewport frames windows at recon- + nection. + +- Changed the way the geometry parameter is used. Now the first time a + session is started it set the internal dimension of the agent root + window, afterwards it only affects the dimension of the external + window on the X server. + +- Corrected splash screen offset at reconnection in fullscreen mode. + +- Agent can be launched in fullscreen mode and his geometry can differ + from the X server geometry. + +- Now Width and Height options are used to store geometry of the + default window even on fullscreen mode, and to restore the correct + dimension when switching back to window mode from fullscreen + we added two more options. + +- Removed an error in the move viewport procedure that didn't upgrade + the offset of the internal root window when the external root win- + dow was maximized. + +- Unified the initialization of all the geometry related parameters. + +- The window manager detection procedure is now started whenever there + is an attempt to minimize the fullscreen window or to pass to window + mode. + +- Function's optimization for detecting if WM is running. + +- Switching to window mode has been disabled when the window manager + is not running. + +nxagent-1.5.0-7 + +- Now background pixel is not reset at reconnection. + +- Now geometry is parsed also as a command line parameter. + +- Fixed wrong offset of the root window after a reconnection in case + of window mode. + +- Fixed wrong geometry of the nxagent window after a reconnection + in case of window mode. + +- Fixed wrong position of the main window after a reconnection in + case of fullscreen mode. + +- Fixed refreshing windows problems in viewport navigation. Four in- + visible windows are created around the agent window to automatica- + lly generate exposure when the viewport frame is moved or a windows + come out from the non visibile part of the agent window. + +- We need to store the GC records in a list that will be freed in case + the reconnection succed and will be restored in case of failure. We + have to do this because we cannot destroy the GC records in the + disconnect or reconnect procedure, because this way we couldn't + recover from a disconnection or a reconnection failure. + +- Rewritten the reconnection procedure. Since we cannot be sure + that the reconnection will succed we cannot destroy the display + structure, so we postpone the closing of the previous display + with the creation of the new connection. + +nxagent-1.5.0-6 + +- Adjusted usage list in order to show the R parameter for rootless + mode. + +- Added handling of display parameter to option file. + Corrected few typos error, in option file parsing. + +nxagent-1.5.0-5 + +- Removed error that prevented the realization of cursor in eager + mode. + +nxagent-1.5.0-4 + +- Fixed abnormal behaviour of termination dialog, after the keystroke + Ctrl + Alt + T. + +- Fixed segmentation fault in function parsing option file. + +- Fixed various errors on eager encodings. + +- Added lazy command line switch in order to switch lazy encoding + on. + +- Code cleaning. + +- Implemented a signal to switch between two pixmap + realization policies. + +- Corrected an error while defining pixmaps status. + +- Implemented a debug feature, consisting in a method that pushes + the synchronized realization of all the pixmaps. + +- Began implementation of place holders in replacing of images while + they are being loaded. + +- Performed some changes on spreading of pixmaps status information + on copy area. + +- Began implementation of lazy encoding. + +- Changed version to 1.5.0. + +nxagent-1.5.0-3 + +- Removed the option -nogetimage (FRSA052305). + +- Code cleaning in Font.c. + +- Removed NXAGENT_FONTMATCH macro. + +- Removed NXAGENT_FONTCACHE macro. + +- Handled the ReparentNotify event we get when in rootless mode + ours window are reparented from the window manager. Inserted + fake windows to take account of this new parents. + +- Removed the redirection of client message in rootless mode, and + the configuration of the WM_PROTOCOLS properties on all the top + level windows. + +- Removed parent ID from the windows private structure. + +- Implemented screen operation ReparentWindow. + +- Redirect all client message of type WM_PROTOCOLS and value WM_DELETE- + _WINDOW to internal clients in rootless mode. + +- Set the WM_PROTOCOLS property on all the top level window. + +nxagent-1.5.0-2 + +- Changed viewport navigation, in order to make it works in fullscreen + mode. + +- Changed special keystrokes used for closing session and minimizing + fullscreen window. + +- Removed the message 'NX was unable to negotiate a cache + for this session' (FRSA052296). + +- Fixed a minor bug. It made metacity produced a warning when the agent + started up. + +- Code cleaning. + +- Implemented dynamic handling of the main window's size in the X11 + agent (FRSA052264). + +- Implemented dynamic navigation of the main window's viewport in the + X11 agent (FRSA052265). Users can navigate the viewport while keys + Ctrl + Alt are pressed, either by arrows keys or dragging it by the + pointer. + +- Implemented dynamic handling of the full-screen attribute in the + X11 agent. + +- First implementation of dynamic handling of the full-screen + attribute (FRSA052263). + +- Now the X connection descriptor is not closed when disconnected, + because the transport layer still has reference to it. So we want + it busy till we don't close the display, so we shutdown it instead + of closing it. + +- Removed replys when disconnected. + +- Added the X connection number to the set of enabled input devices, at + reconnection. + +- Rewritten the disconnect/reconnect layout. + +- Now in the suspend status nxagent doesn't sleep. + +- Implementing toggle fullscreen special keys. + +nxagent-1.5.0-1 + +- Opened the 1.5.0 branch. + +nxagent-1.4.1-7 + +- Imported changes from nxagent-1.4.0-64 version. + +nxagent-1.4.1-6 + +- Implemented a GC cache for reconnecting pixmap. + +nxagent-1.4.1-5 + +- Handled the situation of disconnect when the pointer has been grabbed. + We disconnect and reconnect the "grabbing" cursor and after reconnection + we fake a button release in order to let client know that the pointer + button has in effect been released. + +- Code cleanup. + +nxagent-1.4.1-4 + +- Imported changes from nxagent-1.4.0-63 version. + +nxagent-1.4.1-3 + +- Imported changes from nxagent-1.4.0-62 version. + +nxagent-1.4.1-2 + +- Cleaned code in the GC reconnection area. + Scratchs GC are now reconnected before of the pixmaps. + +nxagent-1.4.1-1 + +- Opened the 1.4.1 branch. + +nxagent-1.4.0-65 + +- Cosmetic changes to the diagnostic output. + +nxagent-1.4.0-64 + +- Changed the RENDER version advertised to X clients to be the lowest + value between the version of RENDER of nxagent and of the remote X + server. + +- Disabled fast copy area and fast get image flags, if RENDER extension + is not available. + +- At the screen initialization, if we don't have window manager we + grab keyboard to let nxagent get keyboard events. + +- Completely rewritted the handling of KeyPress events, now we moved + all the test for 'special' keybindings in file keystroke.c. Added the + combination MOD1/2-CTRL-SHIFT- for terminate/suspend the session, + we used the combination MOD1/2 in order to let it work even on MacOS + where Alt(MOD1) doesn't seem to be set. + +- Ignored visibility notify events on the icon windows, that were + messing up the agent visibility state. + +- Changed nxagent reaction on VisibilityNotify event. It fixed the + problem with refresh session under Mac OS X with NXDarwin. + +nxagent-1.4.0-63 + +- Reset the congestion state at transport initialization. + +nxagent-1.4.0-62 + +- Fixed the disconnection and reconnection of window that have attached + an animated cursor. + +nxagent-1.4.0-61 + +- Removed the XInputExtension initialization in order to use the more + general mi extension initialization enabled on new mi version. + +- Removed some useless test and logging info on copy area function. + +nxagent-1.4.0-60 + +- Changed the implementation of CopyArea and CopyPlane. + If both drawables are on framebuffer we send NoExpose to clients, + otherwise we use the mi function HandleExposure to calculate the + region to be exposed instead of let mi redo all the copy operation. + +nxagent-1.4.0-59 + +- Disabled use of caching and cleaning of images, if NX transport is + not used. + +nxagent-1.4.0-58 + +- Added timeout on convert selection operation. If timeout has not + expired and is there a pending operation any new request is dropped + and the client notified, until timeout expiration. + +- Corrected a bug that prevented to correctly store last convert se- + lection request time. + +nxagent-1.4.0-57 + +- The Xinput extension is now initialized at startup. This is of + little use because nxagent only needs to support the core pointer + and keyboard. Anyway this allows nxagent to get rid of the warn- + ings printed by some X clients on recent Linux versions when the + extension is not found. + +nxagent-1.4.0-56 + +- Fixed value returned by ConvertSelection. It was the cause of + possible slowndowns during KDE sessions. + +nxagent-1.4.0-55 + +- Agent icon now is loaded from a binary- + embedded Xpm image, if any attempt to + load the default Xpm file from the image + directory or from the path fails. + Removed code used in the old logo drawing + function. + +nxagent-1.4.0-54 + +- Enabled code for sending to client graphics + exposures. Redirecting the ones coming from + remote X server, only if agent window is not + fully visible, and calculating ourselves failure + in CopyArea/Plane and notifying clients. + The only drawback is that we can have double + refresh effect if agent window is covered. + +NOTE: Partially enabled MIT-SHM extension has + been developed but has not been included + in stable release. Included in version + nxagent-1.4.0-53-DAR1. + +nxagent-1.4.0-53 + +- Implemented a reliable technic to detect + if is there any window manager running on + the X server. + +nxagent-1.4.0-52 + +- Fixed a bug that prevented to correctly + notify the client of a successfull convert + selection. + +nxagent-1.4.0-51 + +- Removed a logging error in render initialization. + +nxagent-1.4.0-50 + +- Now we take the ownership of the selection + on "NX_CUT_BUFFER_SERVER" twice, in order + to solve bug in communication with nxclient + to let him see our main window and know that + agent established connection with X server. + +nxagent-1.4.0-49 + +- Fixed the colormask layout of the visual + used to put images on the real X server when + the drawable has an alpha channel, according + to the endianess of the X server. + +nxagent-1.4.0-48 + +- Moved up the render compatibility limit, + due to the inclusion of the support for render + cursor missing on the 0.2 version. + +nxagent-1.4.0-47 + +- Changing artsd forwarding port from display + + 8000 to display + 7000 + +- Stoping key release event if key press was + catched before. For Alt-F2/F4 combination. + +- Preserved the alpha data on drawables that + are not used by picture but have a depth of 32. + +nxagent-1.4.0-46 + +- Rewritten all the code regarding to the + acceleration for the Render creation of the + cursor, and removed the acceleration for + the animated cursor. + +nxagent-1.4.0-45 + +- The two RENDER operations creating cursors and + animated cursors have been accelerated by for- + warding the original operation to the X server. + +nxagent-1.4.0-44 + +- Fixed a problem in the clipboard procedure. + Now when we get a request of the selection + from an internal client we have to, if the + owner is on the X server, forward the request + to X, otherwise we have to pass the request + to our internal client. + But for a problem in this procedure we passed, + in some situation, the request to the internal + client even if the owner was on the other side. + +- Fixed a segmentation problem in the render + extension by removing composite trapezoid + operation on window. + +nxagent-1.4.0-43 + +- Added some pointer sanity check in the discon- + nect procedure. The problem was arising because + we were executing the code twice when after + began a voluntar disconnection the X connect- + ion was broken for a network failure. + +- Changed directory where nxagent gets the icon. + +- Fixed missing implementation of rendering + trapezoids. + +- Fixed bug in render extension when the nxagent + create cursor diffrent then 32 bits format. + +nxagent-1.4.0-42 + +- Solved segmentation fault, caused by a longjmp + on a stack context not previously saved. + +nxagent-1.4.0-41 + +- Added an exposures of the window in a resize + operation. + +nxagent-1.4.0-40 + +- Implemented a timeout on the opening of the X + display, if we get it we reject all well known + sockets. + +nxagent-1.4.0-39 + +- Corrected minor error on events handling. + +nxagent-1.4.0-38 + +- Removed in the resize window code some exposure + that generated useless traffic. + +- Option geometry is no more parsed in the option + file. + +nxagent-1.4.0-37 + +- When session is suspended and we get TERM signal + nxagent just exit instead of just breaking out of + dispatch loop because we get a terminate exception. + Cleared display variable after having closed the + connection with the X server. + +nxagent-1.4.0-36 + +- Refined some details in the ICC with nxclient. + +nxagent-1.4.0-35 + +- Implemented a new method to comunicate to nxclient, + the raise of the agent root window, taking the ownership + of the selection "A-{MD5 of session}". + Used the same selection to let nxclient comunicate to agent + by changing the property on the same string, when the user + choose by the administrator to terminate or suspend the + session. + +nxagent-1.4.0-34 + +- Key sequence to Suspend/Terminate session (Alt-F4). + +- Key sequence to Minimize session in fullscreen mode (Alt-F2). + +- Check if WM is started, for Alt-F2 sequence. + +- Corrected calculation geometry of exposed region + sent to client after reconnection. + This solve a serious memory leak of nxagent. + +- Fixed a bug in validate GC code that passed + a wrong pointer of tile to framebuffer. + +nxagent-1.4.0-33 + +- Changed the reconnection state machine in order + to let agent exit if has got the TERM signal. + +nxagent-1.4.0-32 + +- Fixed memory leak in option parser that wasted + memory if more than one occurence of 'option' + argument would have been parsed. + +- Removed a invalid read in Keyboard initialization. + Now kbtype option value is copyed instead that + referenced. + +- The X connection number is recorded only after + having cheched for display being successfully opened. + +nxagent-1.4.0-31 + +- Fixed memory leak problem caused by region not + beeing destroyed previously. + +- Fixed a memory leak in keyboard initialization. + +- Fixed a bug in the function that parse the option file, + we were reading the options in the format NAME=VALUE and + were passing it to the argument parser in the format + {NAME, VALUE}, without the prepending '-' in front of NAME. + +nxagent-1.4.0-30 + +- Readded option persistent in order to let nxagent + works with older nxserver that are still launching + nxagent with the persistent option. + +nxagent-1.4.0-29 + +- Corrected the message of the client dialog + asking if user want to suspend or terminate the + session. + +- Chenged the default value for persistence of session + in nxagent to true. Change the persistent option to + nopersistent in order to disable it. + +nxagent-1.4.0-28 + +- Added check on screen initialization of possible + memory allocation failure. + +- Changed the parsing policies of the option file. + Now we are just considering kbtype and geometry + options. + +- Removed testing code that forced rootless mode + when geometry is 100X100. + +- Correctly initialized and mapped the icon window + on fullscreen mode. + +nxagent-1.4.0-27 + +- Fixed lost memory problem caused by second + initialization of screen privates. Screen + privates is already initialized by miScreenInit + function. + +nxagent-1.4.0-26 + +- Added option command line option. This parameter + is used to show complete path to option file. + +- Added parser of the option file. + +- Now default value for fast copy area and fast + getimage is true. + +nxagent-1.4.0-25 + +- Done some cleanup to the initialization of the + defaults drawables at reconnection, and removed + a memory leak in the reopening of the Display. + +nxagent-1.4.0-24 + +- Changed the version number, printed at startup. + +- Removed a memory leak in the font reconnection stage. + +nxagent-1.4.0-23 + +- Removed a bug that messed up the render status info + if reconnected to a display with no render support. + Anyway nxserver should prevent agent to trying reconn- + ecting to such display. + +nxagent-1.4.0-22 + +- Enhanced the reconnection error reporting function. + +nxagent-1.4.0-21 + +- Get the ownership of selection NX_CUT_BUFFER_SERVER at reconnection + in order to let client knows that agent windows has started + successfully. + +nxagent-1.4.0-20 + +- Now we draw splash logo at reconnection. And destroy it and show + all other windows when reconnection has done all in once. We draw + it on default window instead that on root window, and we map root + window when reconnection has finished. + +nxagent-1.4.0-19 + +- Removed the old Xconnection descriptor and added the new one + to the device set, instead of resetting the entire enabled + device set, at reconnection. + +nxagent-1.4.0-18 + +- Reset the enabled devices set of descriptors, and properly + add to this set the the Xconnection descriptor. + +NOTE: This solves all the known solaris reconnection problems. + (The problem appear only on solaris because on this machine + the Xconnection descriptor is changing at reconnection.) + +nxagent-1.4.0-17 + +- Restored the previously owned primary selection, at reconnection. + Removed the handling of the return value of XSetSelectionOwner, + man page doesn't specify any return value. + +nxagent-1.4.0-16 + +- Added compatibility with older windows clients(Xserver) + that send a WM_DELETE_WINDOW client message WM_DELETE_WINDOW + to all top level window and so agent show more than one + NXDialog asking for confirmation, instead of sending just the + message to top level window that are visible and haven't set + the override redirect option. + +nxagent-1.4.0-15 + +- Ignored unmatched DirectColor visuals at reconnection + on a different display not providing it. + +nxagent-1.4.0-14 + +- Moved the render query extension in display + initialization from screen initialization. + +- Changed reconnection policy to disallow reconnect a + session that is using render to a server not providing it. + +nxagent-1.4.0-13 + +- Unified the screen opening function. + +- Changed the reconnection requirements + policy about geometry of X server. + Now agent doesn't accept changes of X server + root window size only if in fullscreen mode. + +nxagent-1.4.0-12 + +- Improved failure notification messagges in Display and + font code. + +nxagent-1.4.0-11 + +- Now visuals are properly recreated, in order to reconnect + to another X server. + +- Updated render formats at reconnection. + +nxagent-1.4.0-10 + +- Removed a serious memory leak at reconnection. + +nxagent-1.4.0-9 + +- Added after window reconnection the redisplay of the current + cursor. Done some general cleanup at cursor reconnection code. + +nxagent-1.4.0-8 + +- Unified tha atom creation at reconnect. + +nxagent-1.4.0-7 + +- Dix layer when creating a GC use a default real pixmap as + stipple but agent need a virtual one. This can cause + segmentation fault to agent if is there any apps that use the + default GC stipple created by dix, without changing it. + +nxagent-1.4.0-6 + +- Imported 1.4.0-1-DAR6 from the 1.4.0 development branch. + +- Handled reconnection of window's cursor still not + reconnected at window reconnection. (This because that cursor + is no more a server[nxagent] resource). + +- Set the last image client variable at reconnection in order + to use the visual cache indexed for client number. + Without this we could get a segmentation fault. + +- Handled properly the reconnection of animated cursor. + Modified the procedure of animated cursor creation + in order to empty some unused fields. + +- Removed a 4 bytes memory leak at reconnection. + +- Synced new tree with nxagent-1.3.2-23. + +- Finished the unify of PutImage at reconnection. + Added a Reconnection Trap in order to let screen functions + (like PutImage) knows that are working at reconnection time + and can behave differently. + +- Unified the code for the normal PutImage and the one's used at + reconnection. But the code that calculate the split is still + doubled. + +nxagent-1.4.0-5 + +- Imported 1.3.2-23 from the 1.3.2 development branch, and dropped + the previous 1.4.0 versions. + +nxagent-1.3.2-23 + +- Pixel hints are set according to the display's depth. Added the + defaults to be used on 16 bits. + +nxagent-1.3.2-22 + +- The pixel hint on Solaris is by default 0xffffff. The value can be + overridden by using the -hint option followed by the hex represen- + tation of the color, as in -hint 0xaabbcc. + +nxagent-1.3.2-21 + +- Asynchronous GetImages are now disabled. If fast GetImage mode is + enabled, agent will always try to guess the pixel to be used for + the solid pattern, based, at its best, on the geometry of the pro- + vided area. This behaviour can be overridden by passing the -slow + parameter on the command line. Slow mode is also the default when + selecting WAN or LAN link settings. + +- Code cleanup in preparation of the final release. + +nxagent-1.3.2-20 + +- New code uses sigaction to set the SIGHUP handler in persistent + mode. Contrarily to signal(), the sigaction call doesn't seem to + reset the handler to SIG_DFL after the signal has been caught. + This problem seems to be specific of Solaris. + +- Client messages of type WM_PROTOCOLS are now handled even when + a window manager is not detected at agent startup. + +- Removed handling of GraphicsExposure coming fron the real server. + Agent will still generate events in the MI. Code dealing with the + remote events needs to be better tuned as it seems to cause some + troubles with double refreshes. + +nxagent-1.3.2-19 + +- Starting from this version agent doens't use NXSync and NXKarma + messages to manage bandwidth arbitration among clients but makes + efficient use of the congestion notification messages introduced + in 1.3.1. A new handler has been added to manage the congestion + state. The handler will block, if needed, waiting for the decon- + gestion notification coming from proxy. + +nxagent-1.3.2-18 + +- Rewritten the block handlers to check the event queue more often. + The new code seems to greatly enhance responsiveness, especially + on fast links. + +- Now agent will handle the expose events coming from the remote + display inside the event dispatcher. + +- Created a new function collecting the expose events. Function is + optimized to add all the expose events for the same window to a + single region. Region is passed to the mi when the last event + has been processed. + +- Still dealing with GetImage from OpenOffice. Now we try to match + the geometry of the incoming requests with known geometry of most + of its graphic elements. It seem to work on Fedora. + +nxagent-1.3.2-17 + +- Added swapping of image data in nxagentGetImage() when connecting + to a display having a different image byte order than the agent + server. + +- Added a new nxagentImageReformat() function in GCOps.c. + +- Now agent will not try to pack images having a data size smaller + than 768 bytes. The previous threshold was set to 64. The Mandrake + vesion of KDE seems to send lot of such small images. Compressed + through JPEG, these images obtain a very poor ratio of nearly 1:1. + +- Added a function translating and sending the GraphicsExposures + events received from the remote server to the agent's clients. + +- Renamed the functions providing the ad-hoc handling of remote X + events. + +nxagent-1.3.2-16 + +- Implemented a cache for the alpha channel data. With clients + making heavy use of the alpha blending, the new cache is able to + cut by nearly 30% the traffic incoming to proxy, offering compara- + ble savings in CPU performance. While proxy is usually able to + cache almost all the alpha traffic, when caching is not enabled + (f.e. when link setting is WAN or LAN) this data is sent uncomp- + ressed by the agent. Tests running common desktop environments + showed that alpha channel could weight up to 2 times the corres- + ponding data generated by the packed images. + +- Fixed the compilation warnings in NXrender.c. + +nxagent-1.3.2-15 + +- Rewritten handling of GetImage from dispatcher down to GCOps. If + the fast GetImage mode is enabled agent will use the asynchronous + calls provided by nxcompext to get data from the real server. Data + collected from the last get image performed is preserved and the + upper left pixel is used to guess a solid background. + +- Added a nxagentGetBackgroundImage() function to apply a similar + mechanism when the nxagent window isn't fully visible. Previously + a solid white background was returned. The new handling seems to + correctly match the window background in most cases. + +- Fixed a problem passing the bytes per line value when creating a + XYPixmap image. The previously calculated value didn't take into + account the depth of the image. + +- Now image's bytes per line, length and visual are calculated by + using a few utility functions added to GCOps.c. + +- Added declaration of the nxagentVisibility related variables to + Window.h. + +nxagent-1.3.2-14 + +- On Fedora xbcomp configuration fails when agent is run nested. + This causes keyboard to ignore most AltGr keys. Strangely enough + this behaviour has been observed only with KDE while GNOME does + not seem to be affected. Reason is to be investigated. + +- Auto-repeat mode of the agent's keyboard device is now always + disabled. Agent will leverage auto-repeated keystrokes genera- + ted on the real server even when propagating device configura- + tion changes. + +- The info output telling if agent will propagate the changes to + devices' setting is now printed after having initialized the + screen. The purpose would be to verify if agent is running in + fullscreen mode and there is no WM on the real display. In this + case we should forcibly propagate device configuration changes. + Unfortunately, due to the way intern atoms are collected, this + is not going to work on platforms where sessions are likely to + run on an existing X server. + +nxagent-1.3.2-13 + +- Fixed a problem with XYPixmaps being used in PutImage with the + wrong left pad. This is a step forward in the solution of the + corrupted masks displayed by Mozilla when showing some animated + GIFs. + +- By selecting 'fast' mode nxagent will now skip real XGetImage + operations on windows. This becomes the default in the case of + MODEM, ISDN and ADSL links. In theory X clients should never do + that. In practice a few naive programs and libraries (like, sur- + prisingly enough, a famous Linux office automation suite) do, + mainly to compose images with the window's backgound. Why don't + they compose content into a Pixmap? + +- Improved the implementation of CompositeGlyphs. It now uses a + single call to XRenderCompositeText instead of splitting the + output in multiple RENDER requests. + +- In previous versions file NXmiwindow.o was not linked into the + resulting nxagent. This solves the problem of missing repaints + in CDE and other Xt applications. Be sure you upgrade nx-X11 + to version nx-X11-1.3.2-2. + +- Added a warning when the change keyboard control or the change + pointer control functions are called. + +nxagent-1.3.2-12 + +- Added bit-swapping of glyphs having depth 1 when agent has a + different bitmap-bit-order than the X server. + +- The KeyRelease event's timestamp calculation, accounting for + differences in time between the local and the remote machine, + will now use the timestamp taken from the last KeyPress. Using + the timestamp of the last event was sometimes causing time to + go backward with the result that server could remain grabbed. + This solves the long-standing "mouse stop responding" problem. + +- Fixed a problem handling the alpha channeled visual introduced + while experimenting with the new server endianess layout. + +nxagent-1.3.2-11 + +- Added the Reset option to options repository. By default agent + will skip server reset when the last client disconnects. This is + equivalent to passing the -noreset option to a standard XFree86 + server. To restore the original behaviour the new -reset option + can be used on the command line. + +- Moved the SharedMemory and DeviceControl options to the options + repository. + +- A basic session, still leveraging all the default facilities, can + now be run as: nxagent -name NX -geometry 800x600+10+100 :1. The + -fp unix/:7100 option can be added to enable access to the X font + server. + +- Fixed a "unused variable" warning in Cursor.c. + +nxagent-1.3.2-10 + +- Rootless mode. Some cleanup in initialization. + +- Rootless mode. Working at the configure-window errors. + +nxagent-1.3.2-9 + +- Removed limitations when running nxagent nested inside another + nxagent server. Now both render extension and packing of images + are enabled. + +- The nxagent X server now inherits its endianess from the host + architecture, instead of assuming the same endianess of the con- + necting client. This fixes the remaining problems running ses- + sions nested inside another nxagent server. + +- Removed any reference to ReformatImage(). + +nxagent-1.3.2-8 + +- Changed the way the agent server handles images internally. + The inherited Xnest code used to set the server's image order + to the same order of the remote X display. This caused agent + to create images in the internal frame-buffer with a different + endianess in respect to images got from X clients. + +- The new image handling code seems to solve all the known image + endianess problems, for example cursors created on big-endian + displays with a wrong shape or glyphs being showed flipped when + retrieving the image data from the virtual frame-buffer. + +- As an added bonus the new code seems to double the performance + of the SPARC Solaris server when accessing i386 clients. + +- Commented out all the existing calls to ReformatImage(). Code + needs now extensive testing to see if any of the calls must be + actually restored. + +- Replaced calls to index() with strchr(). + +nxagent-1.3.2-7 + +- Solved a potential memory error when accessing a client or a + window pointer in clipboard management code after the resources + had been destroyed. Added a nxagentClearClipboard() function to + be called before a client or a window is destroyed to get rid + of any reference to the disposed resources. + +- Auto-repeated keystrokes generated by agent from inside the + virtual keyboard device are now ignored. Agent will correctly + honor auto-repeated keystrokes generated by the real X server. + This is actually the expected behaviour. The former implemen- + tation triggered an annoying bug, with keystrokes being inad- + vertedly auto-repeated in the case of high latency on the + network link. + +- Agent will now ignore the pointer settings changes generated + inside the remote session. The original behaviour was to reset + the pointer values (for example acceleration) to the X factory + settings at session startup. Agent will now inherit whatever + values are set on the real X display. + +- Added a -noignore parameter. When passed, agent will propagate + to the real X server any change to keyboard and pointer control + settings operated by its own X clients. + +nxagent-1.3.2-6 + +- Fixed problem with glyphs being drawn clipped in the virtual + frame buffer. This is not yet the final solution but it seems + to work in all the circumstances where problem was observed + in the past. Problem seems to be caused by scratch pixmaps + being requested with a width and height smaller than actually + required. Note anyway that pixmap's buffer seems to be never + accessed beyond its boundary. This probably means that memory + for the pixmap is originally allocated using the right size. + +- Moved backing-store selection to options repository. Now by + default the backing-store mode is set to WhenRequested. This + means that, in most cases, there is no need to pass the -bs + option on the command line. + +- Code cleanup in Render.c, NXrender.c, NXglyph.c. + +nxagent-1.3.2-5 + +- Fixed initialization of all the supported depths. Previous + versions correctly initialized the various depths but still + failed to advertise the support of any other depth than the + default depth supported by the remote X server. + +- Persistent mode. We now correctly propagate the pixmap ID of + the parent to the virtual pixmap at reconnection. This fixes + the reconnection errors when render extension is enabled. + +- Persistent mode. Solved the refresh problems at reconnection. + Problems were generated by the lack of window parent's ID at + the time session was reconnected. + +- Changed the agent's behaviour at the time the close button is + pressed. If agent is running in persistent mode a new dialog + is showed with the option to suspend the session. + +nxagent-1.3.2-4 + +- Persistent mode. At the time the proxy connection is reset the + per-client unpack geometry information is cleared. This makes + agent find out that a new unpack geometry is needed as soon as + the display is reconnected. + +- Persistent mode. Lot of logging added in order to trace use of + resources as long as they are recreated. The current version + fails to correctly restore the picture information when render + is enabled. + +nxagent-1.3.2-3 + +- Finally fixed all the problems with missing initialization of + pixmap formats. The screen info is now correctly set up even + when the remote display doesn't support all the target depths. + Many thanks to Michael L Torrie who helped me to reproduce the + problem and come to a solution. + +- Moved initialization of depths, default drawables and pixmap + formats to their own functions in Display.c. + +nxagent-1.3.2-2 + +- Fixed the nxagentDestroyPixmap() function to correctly take into + account the reference counter of the virtual pixmaps. This solves + the crashes observed when running some GTK clients like xchat. + +- Added a function Pixmap.c to forcibly destroy the pixmaps created + in the virtual framebuffer when the parent pixmap is destroyed. + +- This version contains some verbose output intended to better test + the new behaviour. The output will be removed in future versions. + +nxagent-1.3.2-1 + +- More cleanup in Pixmap.c. + +- Rewritten nxagentCreatePixmap(). Corrected an error where the + bitsPerPixel field was set to the pixmap's depth instead of the + result of BitsPerPixel(depth). This finally solves the problem + of text being incorrectly rendered in the virtual framebuffer. + +- Corrected the X error returned at the end of session when trying + to free a pixmap with an invalid id. + +- Opened the 1.3.2 branch. + +nxagent-1.3.1-32 + +- Cleanup of Pixmap.h/Pixmap.c. Renamed macros according to the + nxagent naming conventions. + +nxagent-1.3.1-31 + +- When running in fullscreen mode, grab and ungrab of pointer and + keyboard is performed in new functions, placed in Events.c. + +- The event loop now checks if the enter/leave notify carries a + NotifyInferior detail and, in this case, doesn't perform the grab. + This saves half the amount of grabs (and the related roundtrips) + performed by the previous version. + +- Ungrab of pointer is now performed whenever the cursor leaves the + fullscreen window. In previous version only the keyboard was + explicitly ungrabbed. + +- Added a warning in the event loop when receiving a MappingNotify. + This event is presently unhandled and seems to be reported, as a + consequence of the selected event mask, only by some X servers. + +nxagent-1.3.1-30 + +- Reverted the patch introduced in Pixmap.c. The whole issue is + being investigated in its ramifications up to the virtual frame + buffer. + +nxagent-1.3.1-29 + +- Fixed a problem in the nxagentDestroyPixmap function where the + reference counter of pixmaps could be decremented twice. This + could lead to agent trying to free the pixmaps more than once. + +- On Solaris there is no description for pc105 keyboard model. As + a workaround we consider pc104 to be the closest approximation. + +nxagent-1.3.1-28 + +- Fixed a bug in the create window procedure. With some clients, + like Maelstrom and xmame, the creation of the main window was + failing due to the wrong colormap and visual attributes used + by agent on the real X server. + +- In fullscreen mode the keyboard is now grabbed at the time we + receive an EnterNotify event. This fixes a problem at startup + observed on some Debian based distributions where agent didn't + receive the keyboard focus until user had minimized and then + brought to front the agent's window. The grab is now correctly + performed by using the timestamp of the remote X server ins- + tead of our local timestamp. + +- In NXdixfonts.c strings corresponding to names of fonts and + font aliases cached by nxagent were missing the terminating + zero. + +- In function InitClientPrivates fixed the missing initializa- + tion of the is_ignored member of the ClientPriv structure. + +- Added the Persistent option to Options repository. The flag is + intended to replace the old nxagentEnableReconnect variable. + +nxagent-1.3.1-27 + +- Fixed a memory allocation problem in Keyboard.c. A string was + allocated in the heap without making enough room for the trail- + ing zero. + +nxagent-1.3.1-26 + +- Added further run-time checks to verify that pixmaps are not + created with bad bit-per-plane settings. This problem seems to + be caused by lack of support by nxagent of some combinations + of depth and visual when the render extension is enabled. If + this is the case, hide the render extension to new clients and + force any subsequent render operation to return a BadRequest + error. This required including extension.c from dix. A new + NXextension.c file is added to the distribution. + +- A problem was reported by Valgrind about reading the first 4 + bytes just after the block allocated in fbCreatePixmap from + nxagentCreatePixmap. A quick fix was added to pixmap.c from + dix so that AllocatePixmap adds 4 additinal bytes to each + buffer. + +nxagent-1.3.1-25 + +- Fixed a memory corruption error. The original AllocateGlyphSet + from render/glyph.c could be called instead of the NX counter- + part defined in NXglyph.c. This could lead to the missing + allocation of the trailing remote glyphset id field. + +- Added initialization of an otherwise usused string in function + nxagentPropagateArtsdProperties(). The whole string is probably + to be removed in future versions. + +- Moved the flag used to avoid reentrancy in GCOps to a separate + Trap header and source. + +- Further cleanup. Removed the zombie file NXglyphcurs.h. + +- Added missing initialization of the picture pointer in private + window's data in nxagentCreateWindow. + +nxagent-1.3.1-24 + +- Added the missing timeout when calling WaitForSomething() at + startup. The bug caused the splash to remain on screen until + a further event was received. + +- Fixed a BadAtom error on Windows during initialization. Error + was caused by a bad attempt to change the NX_AGENT_SIGNATURE. + +- Hunting the 0 bits-per-plane drawable bug in nxagentValidateGC. + Added tracing output and additional checks. GC validation is + skipped if it is not possible to recover an appropriate value. + +- Ensured that nxagentDisplayName is set before calling the post + initialization procedure. + +nxagent-1.3.1-23 + +- When session is run nested inside another NX X agent, all the + optimizations regarding remote expose events on fully visible + windows are disabled. This solves the refresh problems encoun- + tered when covering the nested session with a window from the + local X server. + +- Reusing NX_AGENT_SIGNATURE atom to detect nested operation. + Atom is created internally to the agent server at startup, + before any atom on the real display. + +- Fixed construction of caption used for dialog boxes spawn by + agent. The previous algorithm failed to identify the correct + string in parameter -name passed on the command line. + +nxagent-1.3.1-22 + +- Ensured that state of keyboard modifiers is initialized with + values from the real X server when the first key stroke is + pressed by the user. + +- Fixed the X_SetInputFocus errors generated at session startup. + +- Rootless mode. Ensured that remote expose events are always + reported by the remote proxy. This is a temporary fix looking + forward for better handling of visibility events. + +nxagent-1.3.1-21 + +- Saved a GetWindowAttributes and a GetGeometry in the function + drawing the splash screen. + +- Better handling of splash at startup. Removed the flickering on + Windows without recurring to another atom. This is achieved by + optimizing drawing and delaying mapping of the main windows. + +- Modified the magic values activating rootless mode to 100x100. + +- Removed modifications introduced in 1.3.1-20. + +nxagent-1.3.1-20 + +- Working on eliminating the splash screen flickering on Windows + and Darwin. Checked if the NX_SPLASH atom has been created by + the NX X server. If this is the case, we let the NX X server + show the splash screen on our behalf. + +nxagent-1.3.1-19 + +- Improved the initialization phase by removing a GetProperty, an + InternAtom and two GetInputFocus round-trips. + +- Added appropriate masking of the state bits reported by the + XkbStateNotifyMask event. + +- Added a simple mechanism during the itialization phase to trace + the use of X server replies. + +nxagent-1.3.1-18 + +- Made some order in functions loading the NX icon. + +- Removed some more zombie files from agent distribution. Now only + the files imported from DIX and MI have name prepended with NX. + +nxagent-1.3.1-17 + +- Moved names and values of intern atoms created by agent in their + specific header and source. + +- We temporarily force rootless mode if user provides a geometry + of 801x601. This is intended to simplify testing. Note that if + rootless is selected, we'll anyway disregard any geometry set + by the user, assuming the geometry of the real display. + +nxagent-1.3.1-16 + +- We are checking now whether NX_IDENTITY intern atom is created + before NX_SPLASH. We want NX X servers to show the splash on our + behalf, so if NX_SPLASH is already interned, than we just skip + the splash procedure. + +nxagent-1.3.1-15 + +- Rootless mode. Fixed a segfault handling ConfigureNotify events + on top-level windows. + +- Moved handling of ClientMessages coming from proxy in a separate + function. + +nxagent-1.3.1-14 + +- Rewritten the code dealing with key modifier changes. Now we + use XKB events instead of synchronous XkbGetIndicatorState() + calls. + +- Moved activation of keyboard and pointer events to Events.c. + +- Removed pointer motion optimizations as a better logic, taking + in account the selected link speed, is already implemented in + proxy. + +nxagent-1.3.1-13 + +- Renamed the -reconnect option as -persistent. + +- Rootless mode. Agent's root windows are not mapped at startup. + +- Removed the zombie file glyphcurs.c from agent distribution. + +nxagent-1.3.1-12 + +- Corrected a typo in the new CopyArea code in GCOps.c where: + + if (srcx > nxagentWidth) srcx = nxagentWidth; + if (srcy > nxagentHeight) srcx = nxagentHeight; + + had to be: + + if (srcx > nxagentWidth) srcx = nxagentWidth; + if (srcy > nxagentHeight) srcy = nxagentHeight; + +- Added handling of the fullscreen command line parameter to the + options repository. + +- Added agent geometry parameters to the options repository. + +nxagent-1.3.1-11 + +- Rootless mode. Added handling of configuration events reported + for the top-level windows. + +- Rootless mode. Children of the root window get the event mask + selected when the window is created. This makes the keyboard + work at least with xterm and other simple clients. There are + still problems with the pointer events. + +- Created new Splash.h and Splash.c sources file to contain the + few splash screen procedures that were previously sparsed in + multiple files. + +- Added traces in all the window creation procedures and in the + initialization routines called at startup. + +- Renamed some source files to make simpler to identify what is + imported from DIX and what actually pertains to agent. + +nxagent-1.3.1-10 + +- Added the missing RestackWindow screen operation. This solves + problems of incorrect stacking order observed in menus when + using the drop shadow feature in the latest KDE versions. + +nxagent-1.3.1-9 + +- The new standard for checking previous inclusion of headers is + by verifying definition of _Filename_H_ where Filename is the + base name of the file, for example __Options_H__ in the case + of "Options.h". This is intended to be a step in reducing the + number of defines in code prefixed with NXAGENT. + +- Updated NX copyright to year 2004. Placed copyright statement + regarding NXAGENT and NX modifications to the Xnest software + at the beginning of the file. Checked again if credit is given + to all the existing copyright owners. + +nxagent-1.3.1-8 + +- Added a new Options repository to store the values currently + dispersed all over around. The new macros nxagentOption(option) + and nxagentChangeOption(option, value) should be used from now + on to access the important values affecting agent's operations. + +- General cleanup of code. Removed the remaining references to + the Xnest legacy code. + +nxagent-1.3.1-7 + +- Some steps forward toward rootless agent. Now all the top level + windows are correctly created. Drawing to the real screen seems + to work without problems. It is still not possible to get events + in the event loop and the remote WM is interfering with the WM + on the local display. + +- More cleanup of code. Some changes to parts added since 1.3.1-5. + +nxagent-1.3.1-6 + +- A drawable with 0 bpp can somehow arrive to the fb layer. The + problem needs to be better investigated. In the meanwhile a + quick check is added to correctly identify the ill condition. + +- Small fix to allow Num/Caps lock synchronization also on the + windows platform. This is still to be considered beta quality. + +- New options -slow and -fast added to agent. When "fast mode" is + not set, agent will query the remote X server to get real content + of drawables. When fast mode is enabled, agent will save the + round-trip by just clearing the drawable to its background. The + default mode is "slow", thus agent will always query the remote + server. When "fast mode" is explicitly set or when NX transport + is detected and the link is one of MODEM, ISDN and ADSL, agent + will default to "fast mode". This behaviour can be overridden by + system administrators by setting the key AGENT_EXTRA_OPTIONS_X + to "-slow" in node configuration. + +nxagent-1.3.1-5 + +- Created framework for rootless agent. Added a -rootless option. + +- Slowly going toward a better organization of nxagent internals. + Renamed some files and moved things around. Changed some comments + in Screen.c to be more explainatory. + +nxagent-1.3.1-4 + +- Changed default keyboard model to "pc102" (was "pc101") to correct + problems with "<" and ">" keys on the German keyboards and, poten- + tially on other layouts. + +- Added new parameter -kbtype to handle both geometry and layout in + a single form, for example pc102/pl. Parameter -keyboard is still + supported for backward compatibility. + +- Synchronization of Num and Caps lock status is now done comparing + the real keyboard and the internal state at the time nxagent gets + the focus. If state doesn't match, a fake keyboard event is sent. + +nxagent-1.3.1-3 + +- Fixed a further problem on CopyArea between windows and pixmaps. + +nxagent-1.3.1-2 + +- Implemented CopyArea on framebuffer when copying from windows to + pixmaps. Added the -slow command line switch to let nxagent get + the real content of the window from the X server. This requires + an expensive round-trip so it is disabled by default. + +nxagent-1.3.1-1 + +- Opened the 1.3.1 branch. + +nxagent-1.3.0-32 + +- Fixed a bug on 16 bpp displays using render extension. Now only + images which are used by render pictures and which have depth 32 + are created with a different visual color mask. This saves a big + amount of SetUnpackColormap requests. + +nxagent-1.3.0-31 + +- Fixed a bug in nxagentComposite routine. The macro nxgentPicturePriv + was used without checking for a null pointer argument. + +nxagent-1.3.0-30 + +- Limitations on bandwidth introduced whenever the agent's window + is covered are now disabled by default. They can be enabled by + specifying the -limit option on the command line. The -nolimit + option is left for compatibility with the previous versions. + This handy feature caused complaints in the past from users who + instruct window managers to not move the window having focus on + top of the stacking order. + +nxagent-1.3.0-29 + +- Removed the warnings issued at compile time. + +nxagent-1.3.0-28 + +- Replaced the corrupted file nxagent.xpm with the original version. + +nxagent-1.3.0-27 + +- Hopefully fixed all the remained memory leaks. Most problems were + due to agent's render extension not freeing resources on X server. + +- Added support for big-endian X server display on render extension. + Glyphs are reformatted according with the destination order. + +- Added per client information for SetUnpackGeometry, now the unpack + routines should have the correct information for the color mask at + the end of the split process. + + +nxagent-1.3.0-26 + +- Changed the message printed in the log when leaving the dispatch + loop from 'Error' to 'Info'. + +- Moved initialization of _NXFlushSize to nxcompext in order to set + value at the time NXGetControlParameters() is called. + +nxagent-1.3.0-25 + +- Content of selection is now acquired using a single round-trip. + If content exceeds 262144 bytes, it is truncated at that size. + This works in most situations, at least with text, that, by the + way, is the only target supported at the moment. An improvement + would be to modify the state machine in a way that the remaining + data part is got using a second round-trip. This is not difficult + to do and can be considered for future releases. + +- In handling of clipborad we had to disable check on multiple + convert selection requests from the same client. There is a bug + in the algorithm that prevents the counter to be reset at the + appropriate time. This is to be investigated. + +nxagent-1.3.0-24 + +- Added asynchronous handling of GetProperty requests and replies + using the NXCollectProperty and NXGetCollectedProperty requests + and the NXCollectPropertyNotify event in NXclipboard.c and in + Event.c. Implementation is not complete yet and can sometimes + cause X clients to misbehave. + +- Function xnestBitBlitHelper() now always returns NullRegion. + Handling of graphical expose events should be rewritten so that + regions are always generated internally to nxagent. Returning a + null region without checking our event queue, anyway, saves a + flush of the display buffer and doesn't seem to affect the + functionalities. + +- This version comprises modifications to Events.c, GCOps.c, + NXClipboard.c, NXwindow.c and Window.c where I found XSync() + messages (or code used to just send XSync() messages) outside + any #ifdef ..._DEBUG. + +nxagent-1.3.0-16 + +- A dialog is showed at startup if proxy was not able to load a + persistent cache. + +- Reflected changes introduced in NXGetControlParameters() to add + more detailed information about the compression settings. + +- Fixed a potential bug with the name of the agent's display at the + time a dialog had to be showed. String was allocated with only 6 + characters. This could lead to dialogs not being showed using + display ports greater than 9999. + +- NX.h is now included by NXControl.h. Removed #include directives + from other files. diff --git a/nx-X11/programs/Xserver/hw/nxagent/COPYING b/nx-X11/programs/Xserver/hw/nxagent/COPYING new file mode 100644 index 000000000..d511905c1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/nx-X11/programs/Xserver/hw/nxagent/Client.c b/nx-X11/programs/Xserver/hw/nxagent/Client.c new file mode 100644 index 000000000..7e86a03d2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Client.c @@ -0,0 +1,526 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * Used in handling of karma on lost focus. + */ + +#include +#include +#include + +#include "NX.h" + +#include "Xatom.h" +#include "dixstruct.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "osdep.h" + +/* + * NX specific includes and definitions. + */ + +#include "Agent.h" +#include "Args.h" +#include "Display.h" +#include "Client.h" +#include "Dialog.h" +#include "Handlers.h" +#include "Events.h" +#include "Drawable.h" + +/* + * Need to include this after the stub + * definition of GC in Agent.h. + */ + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Returns the last signal delivered + * to the process. + */ + +extern int _X11TransSocketCheckSignal(void); + +/* + * Time in milliseconds of first iteration + * through the dispatcher. + */ + +unsigned long nxagentStartTime = -1; + +/* + * If defined, add a function checking if we + * need a null timeout after a client wakeup. + */ + +#undef CHECK_RESTARTED_CLIENTS + +#ifdef CHECK_RESTARTED_CLIENTS + +void nxagentCheckRestartedClients(struct timeval **timeout); + +#endif + +/* + * Allow attaching private members to the client. + */ + +int nxagentClientPrivateIndex; + +/* + * The master nxagent holds in nxagentShadowCounter + * the number of shadow nxagents connected to itself. + */ + +int nxagentShadowCounter = 0; + +void nxagentInitClientPrivates(ClientPtr client) +{ + if (nxagentClientPriv(client)) + { + nxagentClientPriv(client) -> clientState = 0; + nxagentClientPriv(client) -> clientBytes = 0; + nxagentClientPriv(client) -> clientHint = UNKNOWN; + } +} + +/* + * Guess the running application based on the + * properties attached to its main window. + */ + +void nxagentGuessClientHint(ClientPtr client, Atom property, char *data) +{ + #ifdef TEST + fprintf(stderr, "++++++nxagentGuessClientHint: Client [%d] setting property [%s] as [%s].\n", + client -> index, validateString(NameForAtom(property)), validateString(data)); + #endif + + if (nxagentClientPriv(client) -> clientHint == UNKNOWN) + { + if (property == XA_WM_CLASS && strcmp(data, "nxclient") == 0) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentGuessClientHint: Detected nxclient as [%d].\n", client -> index); + #endif + + nxagentClientHint(client) = NXCLIENT_WINDOW; + } + } + + if (nxagentClientPriv(client) -> clientHint == NXCLIENT_WINDOW) + { + if (property == MakeAtom("WM_WINDOW_ROLE", 14, True) && + strncmp(data, "msgBox", 6) == 0) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentGuessClientHint: Detected nxclient dialog as [%d].\n", client -> index); + #endif + + nxagentClientHint(client) = NXCLIENT_DIALOG; + } + } +} + +void nxagentGuessShadowHint(ClientPtr client, Atom property) +{ + #ifdef DEBUG + fprintf(stderr, "nxagentGuessShadowHint: Client [%d] setting property [%s].\n", + client -> index, + validateString(NameForAtom(property))); + #endif + + if (nxagentClientPriv(client) -> clientHint == UNKNOWN) + { + if (strcmp(validateString(NameForAtom(property)), "_NX_SHADOW") == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentGuessShadowHint: nxagentShadowCounter [%d].\n", + nxagentShadowCounter); + + fprintf(stderr, "nxagentGuessShadowHint: Detected shadow nxagent as client [%d].\n", + client -> index); + + #endif + + nxagentClientHint(client) = NXAGENT_SHADOW; + + nxagentShadowCounter++; + + #ifdef TEST + fprintf(stderr, "nxagentGuessShadowHint: nxagentShadowCounter [%d].\n", + nxagentShadowCounter); + #endif + + /* + * From this moment on we ignore the visibility + * checks to keep the windows updated. + */ + + nxagentChangeOption(IgnoreVisibility, 1); + } + } +} + +void nxagentCheckIfShadowAgent(ClientPtr client) +{ + + if (nxagentClientPriv(client) -> clientHint == NXAGENT_SHADOW) + { + #ifdef TEST + fprintf(stderr, "nxagentCheckIfShadowAgent: nxagentShadowCounter [%d].\n", + nxagentShadowCounter); + + fprintf(stderr, "nxagentCheckIfShadowAgent: Shadow nxagent as client [%d] detached.\n", + client -> index); + + fprintf(stderr, "nxagentCheckIfShadowAgent: Decreasing nxagentShadowCounter.\n"); + #endif + + /* + * We decrease nxagentShadowCounter. + */ + + nxagentShadowCounter--; + + #ifdef TEST + fprintf(stderr, "nxagentCheckIfShadowAgent: nxagentShadowCounter [%d].\n", + nxagentShadowCounter); + #endif + + + if (nxagentShadowCounter == 0) + { + /* + * The last shadow nxagent has been detached + * from master nxagent. + * The master nxagent could do some action + * here. + */ + + #ifdef TEST + fprintf(stderr, "nxagentCheckIfShadowAgent: The last shadow nxagent has been detached.\n"); + #endif + + nxagentChangeOption(IgnoreVisibility, 0); + } + } +} + +void nxagentWakeupByReconnect() +{ + int i; + + #ifdef TEST + fprintf(stderr, "++++++nxagentWakeupByReconnect: Going to wakeup all clients.\n"); + #endif + + for (i = 1; i < currentMaxClients; i++) + { + if (clients[i] != NULL) + { + nxagentWakeupByReset(clients[i]); + } + } +} + +void nxagentWakeupByReset(ClientPtr client) +{ + #ifdef TEST + fprintf(stderr, "++++++nxagentWakeupByReset: Going to check client id [%d].\n", + client -> index); + #endif + + if (nxagentNeedWakeup(client)) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentWakeupByReset: Going to wakeup client id [%d].\n", + client -> index); + #endif + + if (client -> index < MAX_CONNECTIONS) + { + if (nxagentNeedWakeupBySplit(client)) + { + nxagentWakeupBySplit(client); + } + } + } + + if (client -> index < MAX_CONNECTIONS) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentWakeupByReset: Going to reset bytes received for client id [%d].\n", + client -> index); + #endif + + nxagentClientBytes(client) = 0; + } +} + +/* + * Wait for any event. + */ + +#define WAIT_ALL_EVENTS + +#ifndef WAIT_ALL_EVENTS + +static Bool nxagentWaitWakeupBySplitPredicate(Display *display, XEvent *event, XPointer ptr) +{ + return (event -> type == ClientMessage && + (event -> xclient.data.l[0] == NXNoSplitNotify || + event -> xclient.data.l[0] == NXStartSplitNotify || + event -> xclient.data.l[0] == NXCommitSplitNotify || + event -> xclient.data.l[0] == NXEndSplitNotify || + event -> xclient.data.l[0] == NXEmptySplitNotify) && + event -> xclient.window == 0 && event -> xclient.message_type == 0 && + event -> xclient.format == 32); +} + +#endif + +#define USE_FINISH_SPLIT + +void nxagentWaitWakeupBySplit(ClientPtr client) +{ + #ifdef TEST + + if (nxagentNeedWakeupBySplit(client) == 0) + { + fprintf(stderr, "++++++nxagentWaitWakeupBySplit: WARNING! The client [%d] is already awake.\n", + client -> index); + } + + fprintf(stderr, "++++++nxagentWaitWakeupBySplit: Going to wait for the client [%d].\n", + client -> index); + #endif + + /* + * Be sure we intercept an I/O error + * as well as an interrupt. + */ + + #ifdef USE_FINISH_SPLIT + + NXFinishSplit(nxagentDisplay, client -> index); + + #endif + + NXFlushDisplay(nxagentDisplay, NXFlushBuffer); + + for (;;) + { + /* + * Can we handle all the possible events here + * or we need to select only the split events? + * Handling all the possible events would pre- + * empt the queue and make a better use of the + * link. + */ + + #ifdef WAIT_ALL_EVENTS + + nxagentDispatchEvents(NULL); + + #else + + nxagentDispatchEvents(nxagentWaitWakeupBySplitPredicate); + + #endif + + if (nxagentNeedWakeupBySplit(client) == 0 || + NXDisplayError(nxagentDisplay) == 1) + { + #ifdef TEST + + if (nxagentNeedWakeupBySplit(client) == 0) + { + fprintf(stderr, "++++++nxagentWaitWakeupBySplit: Client [%d] can now run.\n", + client -> index); + } + else + { + fprintf(stderr, "++++++nxagentWaitWakeupBySplit: WARNING! Display error " + "detected waiting for restart.\n"); + } + + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "++++++nxagentWaitWakeupBySplit: Yielding control to the NX transport.\n"); + #endif + + nxagentWaitEvents(nxagentDisplay, NULL); + } +} + +int nxagentSuspendBySplit(ClientPtr client) +{ +/* +FIXME: Should record a serial number for the client, so that + the client is not restarted because of an end of split + of a previous client with the same index. +*/ + if (client -> index < MAX_CONNECTIONS) + { + if (nxagentNeedWakeup(client) == 0) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentSuspendBySplit: Suspending client [%d] with agent sequence [%ld].\n", + client -> index, NextRequest(nxagentDisplay) - 1); + #endif + + if (client -> clientGone == 0) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentSuspendBySplit: Client [%d] suspended.\n", client -> index); + #endif + + IgnoreClient(client); + } + } + #ifdef TEST + else + { + fprintf(stderr, "++++++nxagentSuspendBySplit: WARNING! Client [%d] already ignored with state [%x].\n", + client -> index, nxagentClientPriv(client) -> clientState); + } + #endif + + nxagentClientPriv(client) -> clientState |= SleepingBySplit; + + return 1; + } + + #ifdef WARNING + fprintf(stderr, "++++++nxagentSuspendBySplit: WARNING! Invalid client [%d] provided to function.\n", + client -> index); + #endif + + return -1; +} + +int nxagentWakeupBySplit(ClientPtr client) +{ +/* +FIXME: Should record a serial number for the client, so that + the client is not restarted because of the end of the + split for a previous client with the same index. +*/ + if (client -> index < MAX_CONNECTIONS) + { + nxagentClientPriv(client) -> clientState &= ~SleepingBySplit; + + if (nxagentNeedWakeup(client) == 0) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentWakeupBySplit: Resuming client [%d] with agent sequence [%ld].\n", + client -> index, NextRequest(nxagentDisplay) - 1); + #endif + + if (client -> clientGone == 0) + { + AttendClient(client); + } + } + #ifdef TEST + else + { + fprintf(stderr, "++++++nxagentWakeupBySplit: WARNING! Client [%d] still suspended with state [%x].\n", + client -> index, nxagentClientPriv(client) -> clientState); + } + #endif + + return 1; + } + + #ifdef WARNING + fprintf(stderr, "++++++nxagentWakeupBySplit: WARNING! Invalid client [%d] provided to function.\n", + client -> index); + #endif + + return -1; +} + +#ifdef CHECK_RESTARTED_CLIENTS + +void nxagentCheckRestartedClients(struct timeval **timeout) +{ + static struct timeval zero; + + int i; + + /* + * If any of the restarted clients had requests + * in input we'll need to enter the select with + * a null timeout, or we will block until any + * other client becomes available. + */ + + for (i = 1; i < currentMaxClients; i++) + { + if (clients[i] != NULL && clients[i] -> osPrivate != NULL && + nxagentNeedWakeup(clients[i]) == 0) + { + int fd = ((OsCommPtr) clients[i] -> osPrivate) -> fd; + + if (FD_ISSET(fd, &ClientsWithInput)) + { + #ifdef WARNING + fprintf(stderr, "nxagentBlockHandler: WARNING! Client [%d] with fd [%d] has input.\n", + clients[i] -> index, fd); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentBlockHandler: Setting a null timeout with former timeout [%ld] Ms.\n", + (*timeout) -> tv_sec * 1000 + (*timeout) -> tv_usec / 1000); + #endif + + if (*timeout != NULL) + { + (*timeout) -> tv_sec = 0; + (*timeout) -> tv_usec = 0; + } + else + { + zero.tv_sec = 0; + zero.tv_usec = 0; + + *timeout = &zero; + } + } + } + } +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Client.h b/nx-X11/programs/Xserver/hw/nxagent/Client.h new file mode 100644 index 000000000..5f9fa1ebb --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Client.h @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Client_H__ +#define __Client_H__ + +#define MAX_CONNECTIONS 256 + +/* + * The master nxagent holds in nxagentShadowCounter + * the number of shadow nxagents connected to itself. + */ + +extern int nxagentShadowCounter; + +enum ClientHint +{ + UNKNOWN = 0, + NXCLIENT_WINDOW, + NXCLIENT_DIALOG, + NXAGENT_SHADOW +}; + +typedef struct _PrivClientRec +{ + int clientState; + long clientBytes; + enum ClientHint clientHint; + +} PrivClientRec; + +extern int nxagentClientPrivateIndex; + +#define nxagentClientPriv(pClient) \ + ((PrivClientRec *)((pClient)->devPrivates[nxagentClientPrivateIndex].ptr)) + +void nxagentInitClientPrivates(ClientPtr); + +#define nxagentClientAddBytes(pClient, size) \ + (nxagentClientPriv(pClient) -> clientBytes += (size)) + +#define nxagentClientBytes(pClient) \ + (nxagentClientPriv(pClient) -> clientBytes) + +#define nxagentClientHint(pClient) \ + (nxagentClientPriv(pClient) -> clientHint) + +#define nxagentClientIsDialog(pClient) \ + (nxagentClientHint(pClient) == NXCLIENT_DIALOG) + +/* + * The actual reason why the client + * is sleeping. + */ + +#define SleepingBySplit 1 + +#define nxagentNeedWakeup(client) \ + ((nxagentClientPriv(client) -> \ + clientState) != 0) + +#define nxagentNeedWakeupBySplit(client) \ + (((nxagentClientPriv(client) -> \ + clientState) & SleepingBySplit) != 0) + +void nxagentGuessClientHint(ClientPtr, Atom, char*); + +void nxagentGuessShadowHint(ClientPtr, Atom); + +void nxagentCheckIfShadowAgent(ClientPtr); + +/* + * Suspend or restart the agent's + * client. + */ + +int nxagentSuspendBySplit(ClientPtr client); +int nxagentWakeupBySplit(ClientPtr client); + +/* + * Wait until the given client is + * restarted. + */ + +void nxagentWaitWakeupBySplit(ClientPtr client); + +/* +FIXME: This must be moved to Drawable.h. +*/ +void nxagentWaitDrawable(DrawablePtr pDrawable); + +/* + * Wakeup all the sleeping clients. + */ + +void nxagentWakeupByReconnect(void); + +/* + * Reset the client state before + * closing it down. + */ + +void nxagentWakeupByReset(ClientPtr client); + +#endif /* __Client_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c new file mode 100644 index 000000000..b581540cb --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c @@ -0,0 +1,1557 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#define NEED_EVENTS + +#include "X.h" +#include "Xproto.h" +#include "Xatom.h" +#include "selection.h" +#include "windowstr.h" + +#include "Windows.h" +#include "Atoms.h" +#include "Agent.h" +#include "Args.h" +#include "Trap.h" +#include "Rootless.h" +#include "Clipboard.h" + +/* + * Use asyncronous get property replies. + */ + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * These are defined in the dispatcher. + */ + +extern int NumCurrentSelections; +extern Selection *CurrentSelections; + +int nxagentLastClipboardClient = -1; + +static int agentClipboardStatus; +static int clientAccum; + +Atom serverCutProperty; +static Atom clientCutProperty; +static Window serverWindow; + +static const int nxagentPrimarySelection = 0; +static const int nxagentClipboardSelection = 1; +static const int nxagentMaxSelections = 2; + +typedef struct _SelectionOwner +{ + Atom selection; + ClientPtr client; + Window window; + WindowPtr windowPtr; + Time lastTimeChanged; + +} SelectionOwner; + +static SelectionOwner *lastSelectionOwner; +static Atom nxagentLastRequestedSelection; +static Atom nxagentClipboardAtom; +static Atom nxagentTimestampAtom; + +/* + * Needed to handle the notify selection event to + * be sent to client once the selection property + * has been retrieved from the real X server. + */ + +typedef enum +{ + SelectionStageNone, + SelectionStageQuerySize, + SelectionStageWaitSize, + SelectionStageQueryData, + SelectionStageWaitData +} ClientSelectionStage; + +static WindowPtr lastClientWindowPtr; +static ClientPtr lastClientClientPtr; +static Window lastClientRequestor; +static Atom lastClientProperty; +static Atom lastClientSelection; +static Atom lastClientTarget; +static Time lastClientTime; +static Time lastClientReqTime; +static unsigned long lastClientPropertySize; + +static ClientSelectionStage lastClientStage; + +static Window lastServerRequestor; +static Atom lastServerProperty; +static Atom lastServerTarget; +static Time lastServerTime; + +static Atom serverTARGETS; +static Atom serverTEXT; +static Atom clientTARGETS; +static Atom clientTEXT; +static Atom clientCOMPOUND_TEXT; + +static char szAgentTARGETS[] = "TARGETS"; +static char szAgentTEXT[] = "TEXT"; +static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT"; +static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT"; + +extern Display *nxagentDisplay; + +Bool nxagentValidServerTargets(Atom target); +void nxagentSendSelectionNotify(Atom property); +void nxagentTransferSelection(int resource); +void nxagentCollectPropertyEvent(int resource); +void nxagentResetSelectionOwner(void); +WindowPtr nxagentGetClipboardWindow(Atom property, WindowPtr pWin); +void nxagentNotifyConvertFailure(ClientPtr client, Window requestor, + Atom selection, Atom target, Time time); +int nxagentSendNotify(xEvent *event); + +/* + * This is from NXproperty.c. + */ + +int GetWindowProperty(WindowPtr pWin, Atom property, long longOffset, long longLength, + Bool delete, Atom type, Atom *actualType, int *format, + unsigned long *nItems, unsigned long *bytesAfter, + unsigned char **propData); + +Bool nxagentValidServerTargets(Atom target) +{ + #ifdef DEBUG + fprintf(stderr, "nxagentValidServerTargets: Got called.\n"); + #endif + + if (target == XA_STRING) return True; + if (target == serverTEXT) return True; + + return False; +} + +void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow) +{ + int i; + + #ifdef DEBUG + fprintf(stderr, "nxagentClearClipboard: Called with client [%p] window [%p].\n", + (void *) pClient, (void *) pWindow); + #endif + + /* + * Only for PRIMARY and CLIPBOARD selections. + */ + + for (i = 0; i < nxagentMaxSelections; i++) + { + if ((pClient != NULL && lastSelectionOwner[i].client == pClient) || + (pWindow != NULL && lastSelectionOwner[i].windowPtr == pWindow)) + { + #ifdef TEST + fprintf(stderr, "nxagentClearClipboard: Resetting state with client [%p] window [%p].\n", + (void *) pClient, (void *) pWindow); + #endif + + lastSelectionOwner[i].client = NULL; + lastSelectionOwner[i].window = None; + lastSelectionOwner[i].windowPtr = NULL; + lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis(); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + lastServerRequestor = None; + } + } + + if (pWindow == lastClientWindowPtr) + { + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + } + +} + +void nxagentClearSelection(XEvent *X) +{ + xEvent x; + + int i = 0; + + #ifdef DEBUG + fprintf(stderr, "nxagentClearSelection: Got called.\n"); + #endif + + if (agentClipboardStatus != 1 || + nxagentOption(Clipboard) == ClipboardServer) + { + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentClearSelection: SelectionClear event.\n"); + #endif + + while ((i < nxagentMaxSelections) && + (lastSelectionOwner[i].selection != X->xselectionclear.selection)) + { + i++; + } + + if (i < nxagentMaxSelections) + { + if (lastSelectionOwner[i].client != NULL) + { + x.u.u.type = SelectionClear; + x.u.selectionClear.time = GetTimeInMillis(); + x.u.selectionClear.window = lastSelectionOwner[i].window; + x.u.selectionClear.atom = CurrentSelections[i].selection; + + (void) TryClientEvents(lastSelectionOwner[i].client, &x, 1, + NoEventMask, NoEventMask, + NullGrab); + } + + CurrentSelections[i].window = WindowTable[0]->drawable.id; + CurrentSelections[i].client = NullClient; + + lastSelectionOwner[i].client = NULL; + lastSelectionOwner[i].window = None; + lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis(); + } + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; +} + +void nxagentRequestSelection(XEvent *X) +{ + int result; + int i = 0; + XSelectionEvent eventSelection; + + #ifdef DEBUG + fprintf(stderr, "nxagentRequestSelection: Got called.\n"); + #endif + + if (agentClipboardStatus != 1) + { + return; + } + + if (!nxagentValidServerTargets(X->xselectionrequest.target) || + (lastServerRequestor != None) || + ((X->xselectionrequest.selection != lastSelectionOwner[nxagentPrimarySelection].selection) && + (X->xselectionrequest.selection != lastSelectionOwner[nxagentClipboardSelection].selection))) + { +/* +FIXME: Do we need this? + + char *strTarget; + + strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target); + + fprintf(stderr, "SelectionRequest event aborting sele=[%s] target=[%s]\n", + validateString(NameForAtom(X->xselectionrequest.selection)), + validateString(NameForAtom(X->xselectionrequest.target))); + + fprintf(stderr, "SelectionRequest event aborting sele=[%s] ext target=[%s] Atom size is [%d]\n", + validateString(NameForAtom(X->xselectionrequest.selection)), strTarget, sizeof(Atom)); + + if (strTarget != NULL) + { + XFree(strTarget); + } +*/ + eventSelection.property = None; + + if (X->xselectionrequest.target == serverTARGETS) + { + Atom xa_STRING = XA_STRING; + result = XChangeProperty (nxagentDisplay, + X->xselectionrequest.requestor, + X->xselectionrequest.property, + X->xselectionrequest.target, + sizeof(Atom)*8, + PropModeReplace, + (unsigned char*)&xa_STRING, + 1); + eventSelection.property = X->xselectionrequest.property; + } + + if (X->xselectionrequest.target == nxagentTimestampAtom) + { + while ((i < NumCurrentSelections) && + lastSelectionOwner[i].selection != X->xselectionrequest.selection) i++; + + if (i < NumCurrentSelections) + { + result = XChangeProperty(nxagentDisplay, + X->xselectionrequest.requestor, + X->xselectionrequest.property, + X->xselectionrequest.target, + 32, + PropModeReplace, + (unsigned char *) &lastSelectionOwner[i].lastTimeChanged, + 1); + eventSelection.property = X->xselectionrequest.property; + } + } + + eventSelection.type = SelectionNotify; + eventSelection.send_event = True; + eventSelection.display = nxagentDisplay; + eventSelection.requestor = X->xselectionrequest.requestor; + eventSelection.selection = X->xselectionrequest.selection; + eventSelection.target = X->xselectionrequest.target; + eventSelection.time = X->xselectionrequest.time; + + result = XSendEvent(nxagentDisplay, + eventSelection.requestor, + False, + 0L, + (XEvent *) &eventSelection); + + #ifdef DEBUG + if (result == BadValue || result == BadWindow) + { + fprintf(stderr, "nxagentRequestSelection: WARNING! XSendEvent failed.\n"); + } + else + { + fprintf(stderr, "nxagentRequestSelection: XSendEvent sent to window [0x%lx].\n", + eventSelection.requestor); + } + #endif + + return; + } + + /* + * This is necessary in nxagentGetClipboardWindow. + */ + + nxagentLastRequestedSelection = X->xselectionrequest.selection; + + while ((i < nxagentMaxSelections) && + (lastSelectionOwner[i].selection != X->xselectionrequest.selection)) + { + i++; + } + + if (i < nxagentMaxSelections) + { + if ((lastClientWindowPtr != NULL) && (lastSelectionOwner[i].client != NULL)) + { + XConvertSelection(nxagentDisplay, CurrentSelections[i].selection, + X->xselectionrequest.target, serverCutProperty, + serverWindow, lastClientTime); + + #ifdef DEBUG + fprintf(stderr, "nxagentRequestSelection: Sent XConvertSelection.\n"); + #endif + } + else + { + if (lastSelectionOwner[i].client != NULL && + nxagentOption(Clipboard) != ClipboardClient) + { + xEvent x; + + lastServerProperty = X->xselectionrequest.property; + lastServerRequestor = X->xselectionrequest.requestor; + lastServerTarget = X->xselectionrequest.target; + lastServerTime = X->xselectionrequest.time; + + x.u.u.type = SelectionRequest; + x.u.selectionRequest.time = GetTimeInMillis(); + x.u.selectionRequest.owner = lastSelectionOwner[i].window; + + /* + * Fictitious window. + */ + + x.u.selectionRequest.requestor = WindowTable[0]->drawable.id; + + /* + * Don't send the same window, some programs are + * clever and verify cut and paste operations + * inside the same window and don't Notify at all. + * + * x.u.selectionRequest.requestor = lastSelectionOwnerWindow; + */ + + x.u.selectionRequest.selection = CurrentSelections[i].selection; + + /* + * x.u.selectionRequest.target = X->xselectionrequest.target; + */ + + x.u.selectionRequest.target = XA_STRING; + x.u.selectionRequest.property = clientCutProperty; + + (void) TryClientEvents(lastSelectionOwner[i].client, &x, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + + #ifdef DEBUG + fprintf(stderr, "nxagentRequestSelection: Executed TryClientEvents with clientCutProperty.\n"); + #endif + } + else + { + /* + * Probably we must to send a Notify + * to requestor with property None. + */ + + eventSelection.type = SelectionNotify; + eventSelection.send_event = True; + eventSelection.display = nxagentDisplay; + eventSelection.requestor = X->xselectionrequest.requestor; + eventSelection.selection = X->xselectionrequest.selection; + eventSelection.target = X->xselectionrequest.target; + eventSelection.property = None; + eventSelection.time = X->xselectionrequest.time; + + result = XSendEvent(nxagentDisplay, + eventSelection.requestor, + False, + 0L, + (XEvent *) &eventSelection); + + #ifdef DEBUG + fprintf(stderr, "nxagentRequestSelection: Executed XSendEvent with property None.\n"); + #endif + } + } + } +} + +void nxagentSendSelectionNotify(Atom property) +{ + xEvent x; + + #ifdef DEBUG + fprintf (stderr, "nxagentSendSelectionNotify: Sending event to client [%d].\n", + lastClientClientPtr -> index); + #endif + + x.u.u.type = SelectionNotify; + + x.u.selectionNotify.time = lastClientTime; + x.u.selectionNotify.requestor = lastClientRequestor; + x.u.selectionNotify.selection = lastClientSelection; + x.u.selectionNotify.target = lastClientTarget; + + x.u.selectionNotify.property = property; + + TryClientEvents(lastClientClientPtr, &x, 1, NoEventMask, + NoEventMask , NullGrab); + + return; +} + +void nxagentTransferSelection(int resource) +{ + int result; + + if (lastClientClientPtr -> index != resource) + { + #ifdef DEBUG + fprintf (stderr, "nxagentTransferSelection: WARNING! Inconsistent resource [%d] with current client [%d].\n", + resource, lastClientClientPtr -> index); + #endif + + nxagentSendSelectionNotify(None); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + return; + } + + switch (lastClientStage) + { + case SelectionStageQuerySize: + { + /* + * Don't get data yet, just get size. We skip + * this stage in current implementation and + * go straight to the data. + */ + + nxagentLastClipboardClient = NXGetCollectPropertyResource(nxagentDisplay); + + if (nxagentLastClipboardClient == -1) + { + #ifdef WARNING + fprintf(stderr, "nxagentTransferSelection: WARNING! Asyncronous GetProperty queue full.\n"); + #endif + + result = -1; + } + else + { + result = NXCollectProperty(nxagentDisplay, + nxagentLastClipboardClient, + serverWindow, + serverCutProperty, + 0, + 0, + False, + AnyPropertyType); + } + + if (result == -1) + { + #ifdef DEBUG + fprintf (stderr, "nxagentTransferSelection: Aborting selection notify procedure for client [%d].\n", + lastClientClientPtr -> index); + #endif + + nxagentSendSelectionNotify(None); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + return; + } + + #ifdef DEBUG + fprintf (stderr, "nxagentTransferSelection: Setting stage to [%d] for client [%d].\n", + SelectionStageWaitSize, lastClientClientPtr -> index); + #endif + + lastClientStage = SelectionStageWaitSize; + + break; + } + case SelectionStageQueryData: + { + /* + * Request the selection data now. + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentTransferSelection: Getting property content from remote server.\n"); + #endif + + nxagentLastClipboardClient = NXGetCollectPropertyResource(nxagentDisplay); + + if (nxagentLastClipboardClient == -1) + { + #ifdef WARNING + fprintf(stderr, "nxagentTransferSelection: WARNING! Asyncronous GetProperty queue full.\n"); + #endif + + result = -1; + } + else + { + result = NXCollectProperty(nxagentDisplay, + nxagentLastClipboardClient, + serverWindow, + serverCutProperty, + 0, + lastClientPropertySize, + False, + AnyPropertyType); + } + + if (result == -1) + { + #ifdef DEBUG + fprintf (stderr, "nxagentTransferSelection: Aborting selection notify procedure for client [%d].\n", + lastClientClientPtr -> index); + #endif + + nxagentSendSelectionNotify(None); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + return; + } + + #ifdef DEBUG + fprintf (stderr, "nxagentTransferSelection: Setting stage to [%d] for client [%d].\n", + SelectionStageWaitData, lastClientClientPtr -> index); + #endif + + lastClientStage = SelectionStageWaitData; + + break; + } + default: + { + #ifdef DEBUG + fprintf (stderr, "nxagentTransferSelection: WARNING! Inconsistent state [%d] for client [%d].\n", + lastClientStage, lastClientClientPtr -> index); + #endif + + break; + } + } +} + +void nxagentCollectPropertyEvent(int resource) +{ + Atom atomReturnType; + int resultFormat; + unsigned long ulReturnItems; + unsigned long ulReturnBytesLeft; + unsigned char *pszReturnData = NULL; + int result; + + /* + * We have received the notification so + * we can safely retrieve data from the + * client structure. + */ + + result = NXGetCollectedProperty(nxagentDisplay, + resource, + &atomReturnType, + &resultFormat, + &ulReturnItems, + &ulReturnBytesLeft, + &pszReturnData); + + nxagentLastClipboardClient = -1; + + if (result == 0) + { + #ifdef DEBUG + fprintf (stderr, "nxagentCollectPropertyEvent: Failed to get reply data for client [%d].\n", + lastClientClientPtr -> index); + #endif + + nxagentSendSelectionNotify(None); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + if (pszReturnData != NULL) + { + XFree(pszReturnData); + } + + return; + } + + switch (lastClientStage) + { + case SelectionStageWaitSize: + { + #ifdef DEBUG + fprintf (stderr, "nxagentCollectPropertyEvent: Got size notify event for client [%d].\n", + lastClientClientPtr -> index); + #endif + + if (ulReturnBytesLeft == 0) + { + #ifdef DEBUG + fprintf (stderr, "nxagentCollectPropertyEvent: Aborting selection notify procedure for client [%d].\n", + lastClientClientPtr -> index); + #endif + + nxagentSendSelectionNotify(None); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + if (pszReturnData != NULL) + { + Xfree(pszReturnData); + } + + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentCollectPropertyEvent: Got property size from remote server.\n"); + #endif + + /* + * Request the selection data now. + */ + + lastClientPropertySize = ulReturnBytesLeft; + lastClientStage = SelectionStageQueryData; + + nxagentTransferSelection(resource); + + break; + } + case SelectionStageWaitData: + { + #ifdef DEBUG + fprintf (stderr, "nxagentCollectPropertyEvent: Got data notify event for client [%d].\n", + lastClientClientPtr -> index); + #endif + + if (ulReturnBytesLeft != 0) + { + #ifdef DEBUG + fprintf (stderr, "nxagentCollectPropertyEvent: Aborting selection notify procedure for client [%d].\n", + lastClientClientPtr -> index); + #endif + + nxagentSendSelectionNotify(None); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + if (pszReturnData != NULL) + { + Xfree(pszReturnData); + } + + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentCollectPropertyEvent: Got property content from remote server.\n"); + #endif + + ChangeWindowProperty(lastClientWindowPtr, + lastClientProperty, + lastClientTarget, + resultFormat, PropModeReplace, + ulReturnItems, pszReturnData, 1); + + #ifdef DEBUG + fprintf(stderr, "nxagentCollectPropertyEvent: Selection property [%s] changed to [%s]\n", + validateString(NameForAtom(lastClientProperty)), pszReturnData); + #endif + + nxagentSendSelectionNotify(lastClientProperty); + + /* + * Enable further requests from clients. + */ + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + break; + } + default: + { + #ifdef DEBUG + fprintf (stderr, "nxagentCollectPropertyEvent: WARNING! Inconsistent state [%d] for client [%d].\n", + lastClientStage, lastClientClientPtr -> index); + #endif + + break; + } + } + + XFree(pszReturnData); + pszReturnData = NULL; +} + +void nxagentNotifySelection(XEvent *X) +{ + int result; + + XSelectionEvent eventSelection; + + #ifdef DEBUG + fprintf(stderr, "nxagentNotifySelection: Got called.\n"); + #endif + + if (agentClipboardStatus != 1) + { + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentNotifySelection: SelectionNotify event.\n"); + #endif + + if (lastClientWindowPtr != NULL) + { + if ((lastClientStage == SelectionStageNone) && (X->xselection.property == serverCutProperty)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentNotifySelection: Starting selection transferral for client [%d].\n", + lastClientClientPtr -> index); + #endif + + /* + * The state machine is able to work in two phases. In the first + * phase we get the size of property data, in the second we get + * the actual data. We save a round-trip by requesting a prede- + * termined amount of data in a single GetProperty and by discar- + * ding the remaining part. This is not the optimal solution (we + * could get the remaining part if it doesn't fit in a single + * reply) but, at least with text, it should work in most situa- + * tions. + */ + + lastClientStage = SelectionStageQueryData; + lastClientPropertySize = 262144; + + nxagentTransferSelection(lastClientClientPtr -> index); + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentNotifySelection: WARNING! Resetting selection transferral for client [%d].\n", + lastClientClientPtr -> index); + #endif + + nxagentSendSelectionNotify(None); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + } + + return; + } + else + { + int i = 0; + + while ((i < nxagentMaxSelections) && (lastSelectionOwner[i].selection != X->xselection.selection)) + { + i++; + } + + if (i < nxagentMaxSelections) + { + if ((lastSelectionOwner[i].client != NULL) && + (lastSelectionOwner[i].windowPtr != NULL) && + (X->xselection.property == clientCutProperty)) + { + Atom atomReturnType; + int resultFormat; + unsigned long ulReturnItems; + unsigned long ulReturnBytesLeft; + unsigned char *pszReturnData = NULL; + + result = GetWindowProperty(lastSelectionOwner[i].windowPtr, clientCutProperty, 0, 0, False, + AnyPropertyType, &atomReturnType, &resultFormat, + &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); + + if (result == BadAlloc || result == BadAtom || + result == BadMatch || result == BadValue || + result == BadWindow) + { + fprintf (stderr, "Client GetProperty failed error ="); + lastServerProperty = None; + switch (result) + { + case BadAtom: + fprintf (stderr, "BadAtom\n"); + break; + case BadValue: + fprintf (stderr, "BadValue\n"); + break; + case BadWindow: + fprintf (stderr, "BadWindow\n"); + break; + } + } + else + { + result = GetWindowProperty(lastSelectionOwner[i].windowPtr, clientCutProperty, 0, + ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType, + &resultFormat, &ulReturnItems, &ulReturnBytesLeft, + &pszReturnData); + + if (result == BadAlloc || result == BadAtom || + result == BadMatch || result == BadValue || + result == BadWindow) + { + fprintf (stderr, "SelectionNotify - XChangeProperty failed\n"); + + lastServerProperty = None; + } + else + { + result = XChangeProperty(nxagentDisplay, + lastServerRequestor, + lastServerProperty, + lastServerTarget, + 8, + PropModeReplace, + pszReturnData, + ulReturnItems); + } + + /* + * if (pszReturnData) + * { + * free(pszReturnData); + * pszReturnData=NULL; + * } + */ + + } + + eventSelection.type = SelectionNotify; + eventSelection.send_event = True; + eventSelection.display = nxagentDisplay; + eventSelection.requestor = lastServerRequestor; + + eventSelection.selection = X->xselection.selection; + + /* + * eventSelection.target = X->xselection.target; + */ + + eventSelection.target = lastServerTarget; + eventSelection.property = lastServerProperty; + eventSelection.time = lastServerTime; + + /* + * eventSelection.time = CurrentTime; + * eventSelection.time = lastServerTime; + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentNotifySelection: Sending event to requestor.\n"); + #endif + + result = XSendEvent(nxagentDisplay, + eventSelection.requestor, + False, + 0L, + (XEvent *) &eventSelection); + + if (result == BadValue || result == BadWindow) + { + fprintf (stderr, "SelectionRequest - XSendEvent failed\n"); + } + + lastServerRequestor = None; /* allow further request */ + } + } + } +} + +/* + * Acquire selection so we don't get selection + * requests from real X clients. + */ + +void nxagentResetSelectionOwner() +{ + int i; + + if (lastServerRequestor != None) + { + #ifdef TEST + fprintf (stderr, "nxagentResetSelectionOwner: WARNING! Requestor window [0x%lx] already found.\n", + lastServerRequestor); + #endif + + return; + } + + /* + * Only for PRIMARY and CLIPBOARD selections. + */ + + for (i = 0; i < nxagentMaxSelections; i++) + { + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, serverWindow, CurrentTime); + + fprintf (stderr, "nxagentResetSelectionOwner: Reset clipboard state.\n"); + + lastSelectionOwner[i].client = NULL; + lastSelectionOwner[i].window = None; + lastSelectionOwner[i].windowPtr = NULL; + lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis(); + } + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + lastServerRequestor = None; + + return; +} + +void nxagentSetSelectionOwner(Selection *pSelection) +{ + int i; + #ifdef DEBUG + fprintf(stderr, "nxagentSetSelectionOwner: Got called.\n"); + #endif + + if (agentClipboardStatus != 1) + { + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentSetSelectionOwner: Setting selection owner to window [0x%lx].\n", + serverWindow); + #endif + + #ifdef TEST + if (lastServerRequestor != None) + { + fprintf (stderr, "nxagentSetSelectionOwner: WARNING! Requestor window [0x%lx] already found.\n", + lastServerRequestor); + } + #endif + + /* + * Only for PRIMARY and CLIPBOARD selections. + */ + + for (i = 0; i < nxagentMaxSelections; i++) + { + if (pSelection->selection == CurrentSelections[i].selection) + { + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, serverWindow, CurrentTime); + + lastSelectionOwner[i].client = pSelection->client; + lastSelectionOwner[i].window = pSelection->window; + lastSelectionOwner[i].windowPtr = pSelection->pWin; + lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis(); + } + } + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + lastServerRequestor = None; + +/* +FIXME + + if (XGetSelectionOwner(nxagentDisplay,pSelection->selection)==serverWindow) + { + fprintf (stderr, "NXdispatch: SetSelectionOwner OK\n"); + + lastSelectionOwnerSelection = pSelection; + lastSelectionOwnerClient = pSelection->client; + lastSelectionOwnerWindow = pSelection->window; + lastSelectionOwnerWindowPtr = pSelection->pWin; + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + + lastServerRequestor = None; + } + else fprintf (stderr, "nxagentSetSelectionOwner: SetSelectionOwner failed\n"); +*/ +} + +void nxagentNotifyConvertFailure(ClientPtr client, Window requestor, + Atom selection, Atom target, Time time) +{ + xEvent x; + +/* +FIXME: Why this pointer can be not a valid + client pointer? +*/ + if (clients[client -> index] != client) + { + #ifdef WARNING + fprintf(stderr, "nxagentNotifyConvertFailure: WARNING! Invalid client pointer."); + #endif + + return; + } + + x.u.u.type = SelectionNotify; + x.u.selectionNotify.time = time; + x.u.selectionNotify.requestor = requestor; + x.u.selectionNotify.selection = selection; + x.u.selectionNotify.target = target; + x.u.selectionNotify.property = None; + + (void) TryClientEvents(client, &x, 1, NoEventMask, + NoEventMask , NullGrab); +} + +int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, + Window requestor, Atom property, Atom target, Time time) +{ + char *strTarget; + int i; + + if (agentClipboardStatus != 1 || + nxagentOption(Clipboard) == ClipboardServer) + { + return 0; + } + + /* + * There is a client owner on the agent side, let normal stuff happen. + */ + + /* + * Only for PRIMARY and CLIPBOARD selections. + */ + + for (i = 0; i < nxagentMaxSelections; i++) + { + if ((selection == CurrentSelections[i].selection) && + (lastSelectionOwner[i].client != NULL)) + { + return 0; + } + } + + if (lastClientWindowPtr != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentConvertSelection: lastClientWindowPtr != NULL.\n"); + #endif + + if ((GetTimeInMillis() - lastClientReqTime) > 5000) + { + #ifdef DEBUG + fprintf(stderr, "nxagentConvertSelection: timeout expired on last request, " + "notifying failure to client\n"); + #endif + + nxagentNotifyConvertFailure(lastClientClientPtr, lastClientRequestor, + lastClientSelection, lastClientTarget, lastClientTime); + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentConvertSelection: got request " + "before timeout expired on last request, notifying failure to client\n"); + #endif + + nxagentNotifyConvertFailure(client, requestor, selection, target, time); + + return 1; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentConvertSelection: client [%d] ask for sel [%s] " + "on window [%lx] prop [%s] target [%s].\n", + client -> index, validateString(NameForAtom(selection)), requestor, + validateString(NameForAtom(property)), validateString(NameForAtom(target))); + #endif + + strTarget = NameForAtom(target); + + if (strTarget == NULL) + { + return 1; + } + + if (target == clientTARGETS) + { + Atom xa_STRING[3]; + xEvent x; + + xa_STRING[0] = XA_STRING; + xa_STRING[1] = clientTEXT; + xa_STRING[2] = clientCOMPOUND_TEXT; + + ChangeWindowProperty(pWin, + property, + target, + sizeof(Atom)*8, + PropModeReplace, + 3, + &xa_STRING, 1); + + x.u.u.type = SelectionNotify; + x.u.selectionNotify.time = time; + x.u.selectionNotify.requestor = requestor; + x.u.selectionNotify.selection = selection; + x.u.selectionNotify.target = target; + x.u.selectionNotify.property = property; + + (void) TryClientEvents(client, &x, 1, NoEventMask, + NoEventMask , NullGrab); + + return 1; + } + + if (target == MakeAtom("TIMESTAMP", 9, 1)) + { + xEvent x; + int i = 0; + + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != selection) i++; + + if (i < NumCurrentSelections) + { + ChangeWindowProperty(pWin, + property, + target, + 32, + PropModeReplace, + 1, + (unsigned char *) &lastSelectionOwner[i].lastTimeChanged, + 1); + + x.u.u.type = SelectionNotify; + x.u.selectionNotify.time = time; + x.u.selectionNotify.requestor = requestor; + x.u.selectionNotify.selection = selection; + x.u.selectionNotify.target = target; + x.u.selectionNotify.property = property; + + (void) TryClientEvents(client, &x, 1, NoEventMask, + NoEventMask , NullGrab); + + return 1; + + } + } + + if (lastClientClientPtr == client && (GetTimeInMillis() - lastClientReqTime < 5000)) + { + /* + * The same client made consecutive requests + * of clipboard contents with less than 5 + * seconds time interval between them. + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentConvertSelection: Consecutives request from client [%p] selection [%ld] " + "elapsed time [%lu] clientAccum [%d]\n", (void *) client, selection, + GetTimeInMillis() - lastClientReqTime, clientAccum); + #endif + + clientAccum++; + } + else + { + if (lastClientClientPtr != client) + { + clientAccum = 0; + } + } + + if ((target == clientTEXT) || (target == XA_STRING) || (target == clientCOMPOUND_TEXT)) + { + lastClientWindowPtr = pWin; + lastClientStage = SelectionStageNone; + lastClientRequestor = requestor; + lastClientClientPtr = client; + lastClientTime = time; + lastClientProperty = property; + lastClientSelection = selection; + lastClientTarget = target; + + lastClientReqTime = (GetTimeInMillis() - lastClientReqTime) > 5000 ? + GetTimeInMillis() : lastClientReqTime; + + if (selection == MakeAtom("CLIPBOARD", 9, 0)) + { + selection = lastSelectionOwner[nxagentClipboardSelection].selection; + } + + XConvertSelection(nxagentDisplay, selection, XA_STRING, serverCutProperty, + serverWindow, CurrentTime); + + #ifdef DEBUG + fprintf(stderr, "nxagentConvertSelection: Sent XConvertSelection with target=[%s], property [%s]\n", + validateString(NameForAtom(target)), validateString(NameForAtom(property))); + #endif + + return 1; + } + else + { + xEvent x; + + #ifdef DEBUG + fprintf(stderr, "nxagentConvertSelection: Xserver generates a SelectionNotify event " + "to the requestor with property None.\n"); + #endif + + x.u.u.type = SelectionNotify; + x.u.selectionNotify.time = time; + x.u.selectionNotify.requestor = requestor; + x.u.selectionNotify.selection = selection; + x.u.selectionNotify.target = target; + x.u.selectionNotify.property = None; + (void) TryClientEvents(client, &x, 1, NoEventMask, NoEventMask , NullGrab); + return 1; + } + return 0; +} + +int nxagentSendNotify(xEvent *event) +{ + #ifdef DEBUG + fprintf(stderr, "nxagentSendNotify: Got called.\n"); + #endif + + if (agentClipboardStatus != 1) + { + return 0; + } + + if (event->u.selectionNotify.property == clientCutProperty) + { + XSelectionEvent x; + int result; + + /* + * Setup selection notify event to real server. + */ + + x.type = SelectionNotify; + x.send_event = True; + x.display = nxagentDisplay; + x.requestor = serverWindow; + + /* + * On real server, the right CLIPBOARD atom is + * XInternAtom(nxagentDisplay, "CLIPBOARD", 1). + */ + + if (event->u.selectionNotify.selection == MakeAtom("CLIPBOARD", 9, 0)) + { + x.selection = lastSelectionOwner[nxagentClipboardSelection].selection; + } + else + { + x.selection = event->u.selectionNotify.selection; + } + + x.target = event->u.selectionNotify.target; + x.property = event->u.selectionNotify.property; + x.time = CurrentTime; + + #ifdef DEBUG + fprintf(stderr, "nxagentSendNotify: Propagating clientCutProperty.\n"); + #endif + + result = XSendEvent (nxagentDisplay, x.requestor, False, + 0L, (XEvent *) &x); + + if (result == BadValue || result == BadWindow) + { + fprintf (stderr, "nxagentSendNotify: XSendEvent failed.\n"); + } + + return 1; + } + + return 0; +} + +WindowPtr nxagentGetClipboardWindow(Atom property, WindowPtr pWin) +{ + int i = 0; + + #ifdef DEBUG + fprintf(stderr, "nxagentGetClipboardWindow: Got called.\n"); + #endif + + while ((i < nxagentMaxSelections) && + (lastSelectionOwner[i].selection != nxagentLastRequestedSelection)) + { + i++; + } + + if ((i < nxagentMaxSelections) && (property == clientCutProperty) && + (lastSelectionOwner[i].windowPtr != NULL)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentGetClipboardWindow: Returning last clipboard owner window.\n"); + #endif + + return lastSelectionOwner[i].windowPtr; + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentGetClipboardWindow: Returning original target window.\n"); + #endif + + return pWin; + } + +} + +int nxagentInitClipboard(WindowPtr pWin) +{ + int i; + Window iWindow = nxagentWindow(pWin); + + #ifdef DEBUG + fprintf(stderr, "nxagentInitClipboard: Got called.\n"); + #endif + + if (lastSelectionOwner != NULL) + { + xfree(lastSelectionOwner); + lastSelectionOwner = NULL; + } + + lastSelectionOwner = (SelectionOwner *) xalloc(2 * sizeof(SelectionOwner)); + + if (lastSelectionOwner == NULL) + { + FatalError("nxagentInitClipboard: Failed to allocate memory for the clipboard selections.\n"); + } + + nxagentClipboardAtom = nxagentAtoms[10]; /* CLIPBOARD */ + nxagentTimestampAtom = nxagentAtoms[11]; /* TIMESTAMP */ + + lastSelectionOwner[nxagentPrimarySelection].selection = XA_PRIMARY; + lastSelectionOwner[nxagentPrimarySelection].client = NullClient; + lastSelectionOwner[nxagentPrimarySelection].window = WindowTable[0]->drawable.id; + lastSelectionOwner[nxagentPrimarySelection].windowPtr = NULL; + lastSelectionOwner[nxagentPrimarySelection].lastTimeChanged = GetTimeInMillis(); + + lastSelectionOwner[nxagentClipboardSelection].selection = nxagentClipboardAtom; + lastSelectionOwner[nxagentClipboardSelection].client = NullClient; + lastSelectionOwner[nxagentClipboardSelection].window = WindowTable[0]->drawable.id; + lastSelectionOwner[nxagentClipboardSelection].windowPtr = NULL; + lastSelectionOwner[nxagentClipboardSelection].lastTimeChanged = GetTimeInMillis(); + + #ifdef NXAGENT_TIMESTAMP + { + extern unsigned long startTime; + + fprintf(stderr, "nxagentInitClipboard: Initializing start [%d] milliseconds.\n", + GetTimeInMillis() - startTime); + } + #endif + + agentClipboardStatus = 0; + serverWindow = iWindow; + + /* + * Local property to hold pasted data. + */ + + serverCutProperty = nxagentAtoms[5]; /* NX_CUT_BUFFER_SERVER */ + serverTARGETS = nxagentAtoms[6]; /* TARGETS */ + serverTEXT = nxagentAtoms[7]; /* TEXT */ + + if (serverCutProperty == None) + { + #ifdef PANIC + fprintf(stderr, "nxagentInitClipboard: PANIC! Could not create NX_CUT_BUFFER_SERVER atom\n"); + #endif + + return -1; + } + + #ifdef TEST + fprintf(stderr, "nxagentInitClipboard: Setting owner of selection [%s][%d] on window 0x%lx\n", + "NX_CUT_BUFFER_SERVER", (int) serverCutProperty, iWindow); + #endif + + XSetSelectionOwner(nxagentDisplay, serverCutProperty, iWindow, CurrentTime); + + if (nxagentSessionId[0]) + { + #ifdef TEST + fprintf(stderr, "nxagentInitClipboard: setting the ownership of %s to %lx" + " and registering for PropertyChangeMask events\n", + validateString(XGetAtomName(nxagentDisplay, nxagentAtoms[10])), iWindow); + #endif + + XSetSelectionOwner(nxagentDisplay, nxagentAtoms[10], iWindow, CurrentTime); + pWin -> eventMask |= PropertyChangeMask; + nxagentChangeWindowAttributes(pWin, CWEventMask); + } + + if (nxagentReconnectTrap) + { + /* + * Only for PRIMARY and CLIPBOARD selections. + */ + + for (i = 0; i < nxagentMaxSelections; i++) + { + if (lastSelectionOwner[i].client && lastSelectionOwner[i].window) + { + XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, iWindow, CurrentTime); + } + } + } + else + { + lastSelectionOwner[nxagentPrimarySelection].client = NULL; + lastSelectionOwner[nxagentClipboardSelection].client = NULL; + + lastServerRequestor = None; + + lastClientWindowPtr = NULL; + lastClientStage = SelectionStageNone; + lastClientReqTime = GetTimeInMillis(); + + clientCutProperty = MakeAtom(szAgentNX_CUT_BUFFER_CLIENT, + strlen(szAgentNX_CUT_BUFFER_CLIENT), 1); + clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True); + clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True); + clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True); + + if (clientCutProperty == None) + { + #ifdef PANIC + fprintf(stderr, "nxagentInitClipboard: PANIC! " + "Could not create NX_CUT_BUFFER_CLIENT atom.\n"); + #endif + + return -1; + } + } + + agentClipboardStatus = 1; + + #ifdef DEBUG + fprintf(stderr, "nxagentInitClipboard: Clipboard initialization completed.\n"); + #endif + + #ifdef NXAGENT_TIMESTAMP + { + extern unsigned long startTime; + + fprintf(stderr, "nxagentInitClipboard: initializing ends [%d] milliseconds.\n", + GetTimeInMillis() - startTime); + } + #endif + + return 1; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h new file mode 100644 index 000000000..e4bcbf65e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h @@ -0,0 +1,46 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Clipboard_H__ +#define __Clipboard_H__ + +/* + * Create the NX_CUT_BUFFER_CLIENT atom and + * initialize the required property to exchange + * data with the X server. + */ + +extern int nxagentInitClipboard(WindowPtr pWindow); + +/* + * Called whenever a client or a window is + * destroyed to let the clipboard code to + * release any pointer to the referenced + * structures. + */ + +extern void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow); + +extern void nxagentSetSelectionOwner(Selection *pSelection); +extern int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection, + Window requestor, Atom property, Atom target, Time time); + +void nxagentClearSelection(); +void nxagentRequestSelection(); +void nxagentNotifySelection(); + +#endif /* __Clipboard_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Colormap.c b/nx-X11/programs/Xserver/hw/nxagent/Colormap.c new file mode 100644 index 000000000..75758679f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Colormap.c @@ -0,0 +1,577 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "X.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "../../include/window.h" +#include "windowstr.h" +#include "colormapst.h" +#include "resource.h" + +#include "Agent.h" + + +#include "Display.h" +#include "Screen.h" +#include "Colormap.h" +#include "Visual.h" +#include "Windows.h" +#include "Args.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +static ColormapPtr InstalledMaps[MAXSCREENS]; + +static Bool nxagentInstalledDefaultColormap = False; + +Bool nxagentReconnectAllColormap(void *p0); + +Bool nxagentCreateColormap(ColormapPtr pCmap) +{ + VisualPtr pVisual; + XColor *colors; + int i, ncolors; + Pixel red, green, blue; + Pixel redInc, greenInc, blueInc; + + Visual *visual; + int class; + + #ifdef TEST + fprintf(stderr, "nxagentCreateColormap: Going to create new colormap.\n"); + #endif + + pVisual = pCmap->pVisual; + ncolors = pVisual->ColormapEntries; + + pCmap->devPriv = (pointer)xalloc(sizeof(nxagentPrivColormap)); + + if (((visual = nxagentVisual(pVisual))) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentCreateColormap: WARNING: Visual not found. Using default visual.\n"); + #endif + + visual = nxagentVisuals[nxagentDefaultVisualIndex].visual; + class = nxagentVisuals[nxagentDefaultVisualIndex].class; + } + else + { + class = pVisual->class; + } + + + nxagentColormapPriv(pCmap)->colormap = + XCreateColormap(nxagentDisplay, + nxagentDefaultWindows[pCmap->pScreen->myNum], + visual, + (class & DynamicClass) ? + AllocAll : AllocNone); + + switch (class) { + case StaticGray: /* read only */ + colors = (XColor *)xalloc(ncolors * sizeof(XColor)); + for (i = 0; i < ncolors; i++) + colors[i].pixel = i; + XQueryColors(nxagentDisplay, nxagentColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->red[i].co.local.green = colors[i].red; + pCmap->red[i].co.local.blue = colors[i].red; + } + xfree(colors); + break; + + case StaticColor: /* read only */ + colors = (XColor *)xalloc(ncolors * sizeof(XColor)); + for (i = 0; i < ncolors; i++) + colors[i].pixel = i; + XQueryColors(nxagentDisplay, nxagentColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->red[i].co.local.green = colors[i].green; + pCmap->red[i].co.local.blue = colors[i].blue; + } + xfree(colors); + break; + + case TrueColor: /* read only */ + colors = (XColor *)xalloc(ncolors * sizeof(XColor)); + red = green = blue = 0L; + redInc = lowbit(pVisual->redMask); + greenInc = lowbit(pVisual->greenMask); + blueInc = lowbit(pVisual->blueMask); + for (i = 0; i < ncolors; i++) { + colors[i].pixel = red | green | blue; + red += redInc; + if (red > pVisual->redMask) red = 0L; + green += greenInc; + if (green > pVisual->greenMask) green = 0L; + blue += blueInc; + if (blue > pVisual->blueMask) blue = 0L; + } + XQueryColors(nxagentDisplay, nxagentColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->green[i].co.local.green = colors[i].green; + pCmap->blue[i].co.local.blue = colors[i].blue; + } + xfree(colors); + break; + + case GrayScale: /* read and write */ + break; + + case PseudoColor: /* read and write */ + break; + + case DirectColor: /* read and write */ + break; + } + + return True; +} + +void nxagentDestroyColormap(ColormapPtr pCmap) +{ + XFreeColormap(nxagentDisplay, nxagentColormap(pCmap)); + xfree(pCmap->devPriv); +} + +#define SEARCH_PREDICATE \ + (nxagentWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i]) + +static int nxagentCountInstalledColormapWindows(WindowPtr pWin, pointer ptr) +{ + nxagentInstalledColormapWindows *icws = (nxagentInstalledColormapWindows *) ptr; + + int i; + + for (i = 0; i < icws->numCmapIDs; i++) + if (SEARCH_PREDICATE) { + icws->numWindows++; + return WT_DONTWALKCHILDREN; + } + + return WT_WALKCHILDREN; +} + +static int nxagentGetInstalledColormapWindows(WindowPtr pWin, pointer ptr) +{ + nxagentInstalledColormapWindows *icws = (nxagentInstalledColormapWindows *)ptr; + int i; + + for (i = 0; i < icws->numCmapIDs; i++) + if (SEARCH_PREDICATE) { + icws->windows[icws->index++] = nxagentWindow(pWin); + return WT_DONTWALKCHILDREN; + } + + return WT_WALKCHILDREN; +} + +static Window *nxagentOldInstalledColormapWindows = NULL; +static int nxagentNumOldInstalledColormapWindows = 0; + +static Bool nxagentSameInstalledColormapWindows(Window *windows, int numWindows) +{ + if (nxagentNumOldInstalledColormapWindows != numWindows) + return False; + + if (nxagentOldInstalledColormapWindows == windows) + return True; + + if (nxagentOldInstalledColormapWindows == NULL || windows == NULL) + return False; + + if (memcmp(nxagentOldInstalledColormapWindows, windows, + numWindows * sizeof(Window))) + return False; + + return True; +} + +void nxagentSetInstalledColormapWindows(ScreenPtr pScreen) +{ + nxagentInstalledColormapWindows icws; + int numWindows; + + icws.cmapIDs = (Colormap *)xalloc(pScreen->maxInstalledCmaps * + sizeof(Colormap)); + icws.numCmapIDs = nxagentListInstalledColormaps(pScreen, icws.cmapIDs); + icws.numWindows = 0; + WalkTree(pScreen, nxagentCountInstalledColormapWindows, (pointer)&icws); + if (icws.numWindows) { + icws.windows = (Window *)xalloc((icws.numWindows + 1) * sizeof(Window)); + icws.index = 0; + WalkTree(pScreen, nxagentGetInstalledColormapWindows, (pointer)&icws); + icws.windows[icws.numWindows] = nxagentDefaultWindows[pScreen->myNum]; + numWindows = icws.numWindows + 1; + } + else { + icws.windows = NULL; + numWindows = 0; + } + + xfree(icws.cmapIDs); + + if (!nxagentSameInstalledColormapWindows(icws.windows, icws.numWindows)) { + if (nxagentOldInstalledColormapWindows) + xfree(nxagentOldInstalledColormapWindows); + +#ifdef _XSERVER64 + { + int i; + Window64 *windows = (Window64 *)xalloc(numWindows * sizeof(Window64)); + + for(i = 0; i < numWindows; ++i) + windows[i] = icws.windows[i]; + XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + windows, numWindows); + xfree(windows); + } +#else + XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + icws.windows, numWindows); +#endif + + nxagentOldInstalledColormapWindows = icws.windows; + nxagentNumOldInstalledColormapWindows = icws.numWindows; + +#ifdef DUMB_WINDOW_MANAGERS + /* + This code is for dumb window managers. + This will only work with default local visual colormaps. + */ + if (icws.numWindows) + { + WindowPtr pWin; + Visual *visual; + ColormapPtr pCmap; + + pWin = nxagentWindowPtr(icws.windows[0]); + visual = nxagentVisualFromID(pScreen, wVisual(pWin)); + + if (visual == nxagentDefaultVisual(pScreen)) + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), + RT_COLORMAP); + else + pCmap = (ColormapPtr)LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + + XSetWindowColormap(nxagentDisplay, + nxagentDefaultWindows[pScreen->myNum], + nxagentColormap(pCmap)); + } +#endif /* DUMB_WINDOW_MANAGERS */ + } + else + if (icws.windows) xfree(icws.windows); +} + +void nxagentSetScreenSaverColormapWindow(ScreenPtr pScreen) +{ + if (nxagentOldInstalledColormapWindows) + xfree(nxagentOldInstalledColormapWindows); + +#ifdef _XSERVER64 + { + Window64 window; + + window = nxagentScreenSaverWindows[pScreen->myNum]; + XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + &window, 1); + nxagentScreenSaverWindows[pScreen->myNum] = window; + } +#else + XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + &nxagentScreenSaverWindows[pScreen->myNum], 1); +#endif /* _XSERVER64 */ + + nxagentOldInstalledColormapWindows = NULL; + nxagentNumOldInstalledColormapWindows = 0; + + nxagentDirectUninstallColormaps(pScreen); +} + +void nxagentDirectInstallColormaps(ScreenPtr pScreen) +{ + int i, n; + Colormap pCmapIDs[MAXCMAPS]; + + if (!nxagentDoDirectColormaps) return; + + n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); + + for (i = 0; i < n; i++) { + ColormapPtr pCmap; + + pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP); + if (pCmap) + XInstallColormap(nxagentDisplay, nxagentColormap(pCmap)); + } +} + +void nxagentDirectUninstallColormaps(ScreenPtr pScreen) +{ + int i, n; + Colormap pCmapIDs[MAXCMAPS]; + + if (!nxagentDoDirectColormaps) return; + + n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); + + for (i = 0; i < n; i++) { + ColormapPtr pCmap; + + pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP); + if (pCmap) + XUninstallColormap(nxagentDisplay, nxagentColormap(pCmap)); + } +} + +void nxagentInstallColormap(ColormapPtr pCmap) +{ + int index; + ColormapPtr pOldCmap; + + index = pCmap->pScreen->myNum; + pOldCmap = InstalledMaps[index]; + + if(pCmap != pOldCmap) + { + nxagentDirectUninstallColormaps(pCmap->pScreen); + + /* Uninstall pInstalledMap. Notify all interested parties. */ + if(pOldCmap != (ColormapPtr)None) + WalkTree(pCmap->pScreen, TellLostMap, (pointer)&pOldCmap->mid); + + InstalledMaps[index] = pCmap; + WalkTree(pCmap->pScreen, TellGainedMap, (pointer)&pCmap->mid); + + nxagentSetInstalledColormapWindows(pCmap->pScreen); + nxagentDirectInstallColormaps(pCmap->pScreen); + } +} + +void nxagentUninstallColormap(ColormapPtr pCmap) +{ + int index; + ColormapPtr pCurCmap; + + index = pCmap->pScreen->myNum; + pCurCmap = InstalledMaps[index]; + + if(pCmap == pCurCmap) + { + if ((unsigned int)pCmap->mid != pCmap->pScreen->defColormap) + { + pCurCmap = (ColormapPtr)LookupIDByType(pCmap->pScreen->defColormap, + RT_COLORMAP); + (*pCmap->pScreen->InstallColormap)(pCurCmap); + } + } +} + +int nxagentListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds) +{ + if (nxagentInstalledDefaultColormap) + { + *pCmapIds = InstalledMaps[pScreen->myNum]->mid; + + return 1; + } + else + { + return 0; + } +} + +void nxagentStoreColors(ColormapPtr pCmap, int nColors, xColorItem *pColors) +{ + if (pCmap->pVisual->class & DynamicClass) +#ifdef _XSERVER64 + { + int i; + XColor *pColors64 = (XColor *)xalloc(nColors * sizeof(XColor) ); + + for(i = 0; i < nColors; ++i) + { + pColors64[i].pixel = pColors[i].pixel; + pColors64[i].red = pColors[i].red; + pColors64[i].green = pColors[i].green; + pColors64[i].blue = pColors[i].blue; + pColors64[i].flags = pColors[i].flags; + } + XStoreColors(nxagentDisplay, nxagentColormap(pCmap), pColors64, nColors); + xfree(pColors64); + } +#else + XStoreColors(nxagentDisplay, nxagentColormap(pCmap), + (XColor *)pColors, nColors); +#endif +} + +void nxagentResolveColor(unsigned short *pRed, unsigned short *pGreen, + unsigned short *pBlue, VisualPtr pVisual) +{ + int shift; + unsigned int lim; + + shift = 16 - pVisual->bitsPerRGBValue; + lim = (1 << pVisual->bitsPerRGBValue) - 1; + + if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) + { + /* rescale to rgb bits */ + *pRed = ((*pRed >> shift) * 65535) / lim; + *pGreen = ((*pGreen >> shift) * 65535) / lim; + *pBlue = ((*pBlue >> shift) * 65535) / lim; + } + else if (pVisual->class == GrayScale) + { + /* rescale to gray then rgb bits */ + *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; + *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; + } + else if (pVisual->class == StaticGray) + { + unsigned int limg; + + limg = pVisual->ColormapEntries - 1; + /* rescale to gray then [0..limg] then [0..65535] then rgb bits */ + *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; + *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg; + *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; + } + else + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + /* rescale to [0..limN] then [0..65535] then rgb bits */ + *pRed = ((((((*pRed * (limr + 1)) >> 16) * + 65535) / limr) >> shift) * 65535) / lim; + *pGreen = ((((((*pGreen * (limg + 1)) >> 16) * + 65535) / limg) >> shift) * 65535) / lim; + *pBlue = ((((((*pBlue * (limb + 1)) >> 16) * + 65535) / limb) >> shift) * 65535) / lim; + } +} + +Bool nxagentCreateDefaultColormap(ScreenPtr pScreen) +{ + VisualPtr pVisual; + ColormapPtr pCmap; + unsigned short zero = 0, ones = 0xFFFF; + Pixel wp, bp; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++); + + if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap, + (pVisual->class & DynamicClass) ? AllocNone : AllocAll, 0) + != Success) + return False; + + wp = pScreen->whitePixel; + bp = pScreen->blackPixel; + if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) != + Success) || + (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) != + Success)) + return FALSE; + pScreen->whitePixel = wp; + pScreen->blackPixel = bp; + (*pScreen->InstallColormap)(pCmap); + + nxagentInstalledDefaultColormap = True; + + return True; +} + +static void nxagentReconnectColormap(pointer p0, XID x1, pointer p2) +{ + ColormapPtr pCmap = (ColormapPtr)p0; + Bool* pBool = (Bool*)p2; + VisualPtr pVisual; + + #ifdef NXAGENT_RECONNECT_COLORMAP_DEBUG + fprintf(stderr, "nxagentReconnectColormap: %p\n", pCmap); + #endif + + if (!*pBool || !pCmap) + return; + + pVisual = pCmap -> pVisual; + + nxagentColormapPriv(pCmap)->colormap = + XCreateColormap(nxagentDisplay, + nxagentDefaultWindows[pCmap->pScreen->myNum], + nxagentVisual(pVisual), + (pVisual->class & DynamicClass) ? + AllocAll : AllocNone); + + #ifdef NXAGENT_RECONNECT_COLORMAP_DEBUG + fprintf(stderr, "nxagentReconnectColormap: %p - ID %xl\n", + pCmap, nxagentColormap(pCmap)); + #endif +} + +Bool nxagentReconnectAllColormap(void *p0) +{ + int flexibility; + int cid; + Bool success = True; + flexibility = *(int*)p0; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_COLORMAP_DEBUG) + fprintf(stderr, "nxagentReconnectAllColormap\n"); + #endif + + for (cid = 0; (cid < MAXCLIENTS) && success; cid++) + { + if (clients[cid] && success) + { + FindClientResourcesByType(clients[cid], RT_COLORMAP, nxagentReconnectColormap, &success); + } + } + + return success; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Colormap.h b/nx-X11/programs/Xserver/hw/nxagent/Colormap.h new file mode 100644 index 000000000..b0cb2dc5e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Colormap.h @@ -0,0 +1,84 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Color_H__ +#define __Color_H__ + +#define DUMB_WINDOW_MANAGERS + +#define MAXCMAPS 1 +#define MINCMAPS 1 + +typedef struct { + Colormap colormap; +} nxagentPrivColormap; + +typedef struct { + int numCmapIDs; + Colormap *cmapIDs; + int numWindows; + Window *windows; + int index; +} nxagentInstalledColormapWindows; + +#define nxagentColormapPriv(pCmap) \ + ((nxagentPrivColormap *)((pCmap)->devPriv)) + +#define nxagentColormap(pCmap) (nxagentColormapPriv(pCmap)->colormap) + +#define nxagentPixel(pixel) (pixel) + +Bool nxagentCreateColormap(ColormapPtr pCmap); + +void nxagentDestroyColormap(ColormapPtr pCmap); + +void nxagentSetInstalledColormapWindows(ScreenPtr pScreen); + +void nxagentSetScreenSaverColormapWindow(ScreenPtr pScreen); + +void nxagentDirectInstallColormaps(ScreenPtr pScreen); + +void nxagentDirectUninstallColormaps(ScreenPtr pScreen); + +void nxagentInstallColormap(ColormapPtr pCmap); + +void nxagentUninstallColormap(ColormapPtr pCmap); + +int nxagentListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds); + +void nxagentStoreColors(ColormapPtr pCmap, int nColors, xColorItem *pColors); + +void nxagentResolveColor(unsigned short *pRed, unsigned short *pGreen, + unsigned short *pBlue, VisualPtr pVisual); + +Bool nxagentCreateDefaultColormap(ScreenPtr pScreen); + +#endif /* __Color_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Composite.c b/nx-X11/programs/Xserver/hw/nxagent/Composite.c new file mode 100644 index 000000000..9bdbac1b1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Composite.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "scrnintstr.h" +#include "windowstr.h" + +#include "Agent.h" +#include "Screen.h" +#include "Display.h" +#include "Options.h" +#include "Windows.h" + +#undef NXAGENT_UPGRADE + +#ifndef NXAGENT_UPGRADE + +#include "NXcomposite.h" + +#else + +#include "composite.h" + +#endif + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Set if the composite extension is supported + * by the remote display. + */ + +int nxagentCompositeEnable = UNDEFINED; + +void nxagentCompositeExtensionInit() +{ + /* + * Set the flag only if the initialization + * completes. + */ + + nxagentCompositeEnable = 0; + + if (nxagentOption(Composite) == 1) + { + int eventBase, errorBase; + + #ifdef TEST + fprintf(stderr, "nxagentCompositeExtensionInit: Checking if the composite extension is supported.\n"); + #endif + + if (XCompositeQueryExtension(nxagentDisplay, &eventBase, &errorBase) == 1) + { + /* + * At the moment we don't need to care + * the version of the extension. + */ + + #ifdef TEST + + int major = -1; + int minor = -1; + + XCompositeQueryVersion(nxagentDisplay, &major, &minor); + + fprintf(stderr, "nxagentCompositeExtensionInit: The remote display supports version [%d] " + "minor [%d].\n", major, minor); + + if (major < 0 || minor < 2) + { + #ifdef WARNING + fprintf(stderr, "nxagentCompositeExtensionInit: WARNING! Potentially incompatible version " + "[%d] minor [%d] detected.\n", major, minor); + #endif + } + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentCompositeExtensionInit: Enabling the use of the composite extension.\n"); + #endif + + nxagentCompositeEnable = 1; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentCompositeExtensionInit: Composite extension not supported on this display.\n"); + } + #endif + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentRenderExtensionInit: Use of the composite extension not enabled.\n"); + } + #endif +} + +void nxagentRedirectDefaultWindows() +{ + int i; + + if (nxagentOption(Rootless) == 1 || + nxagentCompositeEnable == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentRedirectDefaultWindows: Not redirecting default " + "windows with rootless mode [%d] and composite [%d].\n", + nxagentOption(Rootless), nxagentCompositeEnable); + #endif + + return; + } + + for (i = 0; i < screenInfo.numScreens; i++) + { + WindowPtr pWin = WindowTable[i]; + + ScreenPtr pScreen = pWin -> drawable.pScreen; + + #ifdef TEST + fprintf(stderr, "nxagentRedirectDefaultWindows: WARNING! Redirecting default window id [%ld] " + "to off-screen memory.\n", (long int)nxagentDefaultWindows[pScreen->myNum]); + #endif + + /* + * When trying to redirect only the top level window, + * and not the subwindows, we incur in a strange be- + * haviour. The top level is unmapped, mapped, unmap- + * ped and then reparented. This at first makes the + * agent think that the window manager is gone, then + * the agent window disappears. To make thinks even + * more weird, this happens only at reconnection. + */ + + XCompositeRedirectSubwindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + CompositeRedirectAutomatic); + } +} + +void nxagentRedirectWindow(WindowPtr pWin) +{ + if (nxagentOption(Rootless) == 0 || + nxagentCompositeEnable == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentRedirectWindow: Not redirecting window id [%ld] " + "to off-screen memory with rootless mode [%d] and composite [%d].\n", + nxagentWindow(pWin), nxagentOption(Rootless), + nxagentCompositeEnable); + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentRedirectWindow: WARNING! Redirecting window id [%ld] " + "to off-screen memory.\n", (long int)nxagentWindow(pWin)); + #endif + + XCompositeRedirectWindow(nxagentDisplay, nxagentWindow(pWin), + CompositeRedirectAutomatic); + + nxagentWindowPriv(pWin) -> isRedirected = 1; +} + +void nxagentUnredirectWindow(WindowPtr pWin) +{ + if (nxagentWindowPriv(pWin) -> isRedirected == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentRedirectWindow: Disabling redirection of window id [%ld] " + "to off-screen memory.\n", nxagentWindow(pWin)); + #endif + + XCompositeUnredirectWindow(nxagentDisplay, nxagentWindow(pWin), + CompositeRedirectAutomatic); + + nxagentWindowPriv(pWin) -> isRedirected = 0; + } + #ifdef WARNING + else + { + fprintf(stderr, "nxagentUnredirectWindow: WARNING! The window id [%ld] " + "was not redirected.\n", (long int)nxagentWindow(pWin)); + } + #endif +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Composite.h b/nx-X11/programs/Xserver/hw/nxagent/Composite.h new file mode 100644 index 000000000..5ec1e9888 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Composite.h @@ -0,0 +1,51 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Composite_H__ +#define __Composite_H__ + +/* + * Set if the extension is present and + * its use is enabled. + */ + +extern int nxagentCompositeEnable; + +/* + * Query the composite extension on the + * remote display and set the flag if + * it is supported. + */ + +void nxagentCompositeExtensionInit(void); + +/* + * Let the X server redirect the window + * on the off-screen memory. + */ + +void nxagentRedirectDefaultWindows(void); + +/* + * Enable or disabel the redirection of + * the given window. + */ + +void nxagentRedirectWindow(WindowPtr pWin); +void nxagentUnredirectWindow(WindowPtr pWin); + +#endif /* __Composite_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Cursor.c b/nx-X11/programs/Xserver/hw/nxagent/Cursor.c new file mode 100644 index 000000000..3ca29fa5e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Cursor.c @@ -0,0 +1,601 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "inputstr.h" + +#include "Agent.h" +#include "Display.h" +#include "Options.h" +#include "Screen.h" +#include "Cursor.h" +#include "Image.h" +#include "Visual.h" +#include "Keyboard.h" +#include "Args.h" +#include "Windows.h" +#include "Events.h" +#include "Render.h" +#include "Client.h" + +#include "windowstr.h" +#include "resource.h" + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Defined in Display.c. There are huge + * problems mixing the GC definition in + * Xlib with the server code. This must + * be reworked. + */ + +extern XlibGC nxagentBitmapGC; + +/* + * From NXevents.c. + */ + +extern CursorPtr GetSpriteCursor(void); + +void nxagentConstrainCursor(ScreenPtr pScreen, BoxPtr pBox) +{ + #ifdef TEST + + int width, height; + + width = nxagentOption(RootWidth); + height = nxagentOption(RootHeight); + + if (pBox->x1 <= 0 && pBox->y1 <= 0 && + pBox->x2 >= width && pBox->y2 >= height) + { + fprintf(stderr, "nxagentConstrainCursor: Called with box [%d,%d,%d,%d]. " + "Skipping the operation.\n", pBox->x1, pBox->y1, pBox->x2, pBox->y2); + } + else + { + fprintf(stderr, "nxagentConstrainCursor: WARNING! Called with box [%d,%d,%d,%d].\n", + pBox->x1, pBox->y1, pBox->x2, pBox->y2); + } + + #endif +} + +void nxagentCursorLimits(ScreenPtr pScreen, CursorPtr pCursor, + BoxPtr pHotBox, BoxPtr pTopLeftBox) +{ + *pTopLeftBox = *pHotBox; +} + +Bool nxagentDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + + /* + * Don't define the root cursor + * so that nxagent root window + * inherits the parent's cursor. + */ + + Cursor cursor; + + cursor = (pCursor != rootCursor) ? nxagentCursor(pCursor, pScreen): None; + + if (nxagentOption(Rootless) == False) + { + XDefineCursor(nxagentDisplay, + nxagentInputWindows[pScreen -> myNum], + cursor); + + #ifdef TEST + fprintf(stderr, "nxagentDisplayCursor: Called for cursor at [%p] with private [%p].\n", + (void *) pCursor, pCursor->devPriv[pScreen->myNum]); + #endif + } + + return True; +} + +Bool nxagentRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + XImage *image; + Pixmap source, mask; + XColor fg_color, bg_color; + unsigned long valuemask; + XGCValues values; + + #ifdef TEST + fprintf(stderr, "nxagentRealizeCursor: Called for cursor at [%p].\n", (void *) pCursor); + #endif + + valuemask = GCFunction | + GCPlaneMask | + GCForeground | + GCBackground | + GCClipMask; + + values.function = GXcopy; + values.plane_mask = AllPlanes; + values.foreground = 1L; + values.background = 0L; + values.clip_mask = None; + + XChangeGC(nxagentDisplay, nxagentBitmapGC, valuemask, &values); + + source = XCreatePixmap(nxagentDisplay, + nxagentDefaultWindows[pScreen->myNum], + pCursor->bits->width, + pCursor->bits->height, + 1); + + mask = XCreatePixmap(nxagentDisplay, + nxagentDefaultWindows[pScreen->myNum], + pCursor->bits->width, + pCursor->bits->height, + 1); + + image = XCreateImage(nxagentDisplay, + nxagentDefaultVisual(pScreen), + 1, XYBitmap, 0, + (char *)pCursor->bits->source, + pCursor->bits->width, + pCursor->bits->height, + BitmapPad(nxagentDisplay), 0); + + /* + * If we used nxagentImageNormalize() here, + * we'd swap our own cursor data in place. + * Change byte_order and bitmap_bit_order + * in the image struct to let Xlib do the + * swap for us. + */ + + image -> byte_order = IMAGE_BYTE_ORDER; + image -> bitmap_bit_order = BITMAP_BIT_ORDER; + + NXCleanImage(image); + + XPutImage(nxagentDisplay, source, nxagentBitmapGC, image, + 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); + + XFree(image); + + image = XCreateImage(nxagentDisplay, + nxagentDefaultVisual(pScreen), + 1, XYBitmap, 0, + (char *)pCursor->bits->mask, + pCursor->bits->width, + pCursor->bits->height, + BitmapPad(nxagentDisplay), 0); + + image -> byte_order = IMAGE_BYTE_ORDER; + image -> bitmap_bit_order = BITMAP_BIT_ORDER; + + NXCleanImage(image); + + XPutImage(nxagentDisplay, mask, nxagentBitmapGC, image, + 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); + + XFree(image); + + fg_color.red = pCursor->foreRed; + fg_color.green = pCursor->foreGreen; + fg_color.blue = pCursor->foreBlue; + + bg_color.red = pCursor->backRed; + bg_color.green = pCursor->backGreen; + bg_color.blue = pCursor->backBlue; + + pCursor->devPriv[pScreen->myNum] = (pointer) xalloc(sizeof(nxagentPrivCursor)); + + nxagentCursorPriv(pCursor, pScreen)->cursor = + XCreatePixmapCursor(nxagentDisplay, source, mask, &fg_color, + &bg_color, pCursor->bits->xhot, pCursor->bits->yhot); + + nxagentCursorUsesRender(pCursor, pScreen) = 0; + + #ifdef TEST + fprintf(stderr, "nxagentRealizeCursor: Set cursor private at [%p] cursor is [%ld].\n", + (void *) nxagentCursorPriv(pCursor, pScreen), + nxagentCursorPriv(pCursor, pScreen) -> cursor); + #endif + + XFreePixmap(nxagentDisplay, source); + XFreePixmap(nxagentDisplay, mask); + + return True; +} + +Bool nxagentUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + if (nxagentCursorUsesRender(pCursor, pScreen)) + { + PicturePtr pPicture = nxagentCursorPicture(pCursor, pScreen); + + FreePicture(pPicture, pPicture -> id); + } + + if (nxagentCursor(pCursor, pScreen) != None) + { + XFreeCursor(nxagentDisplay, nxagentCursor(pCursor, pScreen)); + + nxagentCursor(pCursor, pScreen) = None; + } + + xfree(nxagentCursorPriv(pCursor, pScreen)); + + return True; +} + +void nxagentRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor, + Bool displayed) +{ + XColor fg_color, bg_color; + + fg_color.red = pCursor->foreRed; + fg_color.green = pCursor->foreGreen; + fg_color.blue = pCursor->foreBlue; + + bg_color.red = pCursor->backRed; + bg_color.green = pCursor->backGreen; + bg_color.blue = pCursor->backBlue; + + XRecolorCursor(nxagentDisplay, + nxagentCursor(pCursor, pScreen), + &fg_color, &bg_color); +} + +Bool nxagentSetCursorPosition(ScreenPtr pScreen, int x, int y, + Bool generateEvent) +{ + /* + * Don't warp the cursor if the requesting client + * is the server client itself or a shadow agent. + */ + + if (requestingClient != NULL && + requestingClient != serverClient && + nxagentClientHint(requestingClient) != NXAGENT_SHADOW) + { + int i; + + #ifdef TEST + fprintf(stderr, "nxagentSetCursorPosition: Moving the cursor at position [%d,%d].\n", + x, y); + #endif + + for (i = 0; i < nxagentNumScreens; i++) + { + XWarpPointer(nxagentDisplay, nxagentDefaultWindows[i], + nxagentDefaultWindows[pScreen->myNum], + 0, 0, 0, 0, x, y); + } + } + + return True; +} + +void nxagentReconnectCursor(pointer p0, XID x1, pointer p2) +{ + Bool* pBool = (Bool*)p2; + CursorPtr pCursor = (CursorPtr) p0; + + AnimCurPtr ac; + int j; + + #ifdef TEST + fprintf(stderr, "nxagentReconnectCursor: pCursor at [%p]\n", pCursor); + #endif + + #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG + fprintf(stderr, "nxagentReconnectCursor: pCursor at [%p]\n", pCursor); + #endif + + if (!*pBool || !pCursor) + { + return; + } + + if (nxagentCursorPriv(pCursor, nxagentDefaultScreen) == 0) + { + if (nxagentIsAnimCursor(pCursor)) + { + #ifdef TEST + fprintf(stderr, "nxagentReconnectCursor: nxagentIsAnimCursor pCursor at [%p]\n", pCursor); + #endif + + ac = nxagentGetAnimCursor(pCursor); + + for (j = 0; j < ac->nelt; j++) + { + nxagentReconnectCursor (ac->elts[j].pCursor, x1, p2); + + #ifdef TEST + fprintf(stderr, "nxagentReconnectCursor: Iteration [%d] pCursor at [%p]\n", j, ac->elts[j].pCursor); + #endif + } + } + } + + else + { + if (nxagentCursorUsesRender(pCursor, nxagentDefaultScreen)) + { + PicturePtr pPicture = nxagentCursorPicture(pCursor, nxagentDefaultScreen); + int ret = 1; + + nxagentReconnectPicture(pPicture, 0, &ret); + + nxagentRenderRealizeCursor(nxagentDefaultScreen, pCursor); + } + else + { + xfree(nxagentCursorPriv(pCursor, nxagentDefaultScreen)); + if (!nxagentRealizeCursor(nxagentDefaultScreen, pCursor)) + { + fprintf(stderr, "nxagentReconnectCursor: nxagentRealizeCursor failed\n"); + *pBool = False; + } + } + } + + #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG + fprintf(stderr, "nxagentReconnectCursor: %p - ID %lx\n", pCursor, nxagentCursor(pCursor, nxagentDefaultScreen)); + #endif +} + +/* + * The parameter is ignored at the moment. + */ + +void nxagentReDisplayCurrentCursor() +{ + CursorPtr pCursor = GetSpriteCursor(); + + if (pCursor && + nxagentCursorPriv(pCursor, nxagentDefaultScreen) && + nxagentCursor(pCursor, nxagentDefaultScreen)) + { + nxagentDisplayCursor(nxagentDefaultScreen, pCursor); + } +} + +Bool nxagentReconnectAllCursor(void *p0) +{ + int i; + Bool r = True; + + GrabPtr grab = inputInfo.pointer -> grab; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_CURSOR_DEBUG) + fprintf(stderr, "nxagentReconnectAllCursor\n"); + #endif + + for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], RT_CURSOR, nxagentReconnectCursor, &r); + + #ifdef WARNING + + if (r == False) + { + fprintf(stderr, "nxagentReconnectAllCursor: WARNING! Failed to recreate " + "cursor for client [%d].\n", i); + } + + #endif + } + } + + if (grab) + { + nxagentReconnectCursor(grab -> cursor, 0, &r); + } + + return r; +} + +void nxagentDisconnectCursor(pointer p0, XID x1, pointer p2) +{ + Bool* pBool = (Bool *) p2; + CursorPtr pCursor = (CursorPtr) p0; + + AnimCurPtr ac; + int j; + + if (!*pBool || !pCursor) + { + return; + } + + if (nxagentCursorPriv(pCursor, nxagentDefaultScreen) == 0) + { + if (nxagentIsAnimCursor(pCursor)) + { + #ifdef TEST + fprintf(stderr, "nxagentDisconnectCursor: nxagentIsAnimCursor pCursor at [%p]\n", pCursor); + #endif + + ac = nxagentGetAnimCursor(pCursor); + + for (j = 0; j < ac->nelt; j++) + { + nxagentDisconnectCursor (ac->elts[j].pCursor, x1, p2); + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectCursor: Iteration [%d] pCursor at [%p]\n", j, ac->elts[j].pCursor); + #endif + } + } + return; + } + + #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG + fprintf(stderr, "nxagentDisconnectCursor: %p - ID %lx\n", + pCursor, + nxagentCursor(pCursor, nxagentDefaultScreen)); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectCursor: Called with bool [%d].\n", *pBool); + + fprintf(stderr, "nxagentDisconnectCursor: Pointer to cursor is [%p] with counter [%d].\n", + (void *) pCursor, pCursor -> refcnt); + + fprintf(stderr, "nxagentDisconnectCursor: Dummy screen is at [%p].\n", + (void *) nxagentDefaultScreen); + + fprintf(stderr, "nxagentDisconnectCursor: Cursor private is at [%p].\n", + (void *) nxagentCursorPriv(pCursor, nxagentDefaultScreen)); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectCursor: Dummy screen number is [%d].\n", + nxagentDefaultScreen -> myNum); + + fprintf(stderr, "nxagentDisconnectCursor: Cursor is [%ld].\n", + nxagentCursor(pCursor, nxagentDefaultScreen)); + #endif + + nxagentCursor(pCursor, nxagentDefaultScreen) = None; + + if (nxagentCursorUsesRender(pCursor, nxagentDefaultScreen)) + { + PicturePtr pPicture = nxagentCursorPicture(pCursor, nxagentDefaultScreen); + int ret = 1; + + #if defined(NXAGENT_RECONNECT_CURSOR_DEBUG) || defined(NXAGENT_RECONNECT_PICTURE_DEBUG) + fprintf(stderr, "nxagentDisconnectCursor: disconnecting attached picture %p\n", pPicture); + #endif + + nxagentDisconnectPicture(pPicture, 0, &ret); + } +} + +Bool nxagentDisconnectAllCursor() +{ + int i; + Bool r = True; + + GrabPtr grab = inputInfo.pointer -> grab; + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectAllCursor: Going to iterate through cursor resources.\n"); + #endif + + for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], RT_CURSOR, nxagentDisconnectCursor, &r); + + #ifdef WARNING + + if (r == False) + { + fprintf(stderr, "nxagentDisconnectAllCursor: WARNING! Failed to disconnect " + "cursor for client [%d].\n", i); + } + + #endif + } + } + + if (grab) + { + nxagentDisconnectCursor(grab -> cursor, 0, &r); + } + + return r; +} + + +#ifdef NXAGENT_RECONNECT_CURSOR_DEBUG + +void nxagentPrintCursorInfo(CursorPtr pCursor, char msg[]) +{ + fprintf(stderr, "%s: %p - ID %lx - ref count %d\n", + msg, pCursor, nxagentCursor(pCursor, nxagentDefaultScreen), pCursor->refcnt); +} + +void nxagentListCursor(void *p0, void *p1, void *p2) +{ + CursorPtr pCursor = (CursorPtr)p0; + + nxagentPrintCursorInfo(pCursor, "CursorDebug:"); +} + +void nxagentListCursors(void) +{ + int i; + Bool r; + + for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], RT_CURSOR, nxagentListCursor, &r); + + #ifdef WARNING + + if (r == False) + { + fprintf(stderr, "nxagentListCursors: WARNING! Failed to list " + "cursor for client [%d].\n", i); + } + + #endif + } + } + + return True; +} + +#endif /* NXAGENT_RECONNECT_CURSOR_DEBUG */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Cursor.h b/nx-X11/programs/Xserver/hw/nxagent/Cursor.h new file mode 100644 index 000000000..ea1bb30f3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Cursor.h @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Cursor_H__ +#define __Cursor_H__ + +#include "cursorstr.h" +#include "picturestr.h" + +typedef struct { + Cursor cursor; + PicturePtr picture; + int uses_render; + int x; + int y; +} nxagentPrivCursor; + +/* + * _AnimCurElt and _AnimCur already defined in animcur.c. + */ + +typedef struct _AnimCurElt { + CursorPtr pCursor; + CARD32 delay; +} AnimCurElt; + +typedef struct _AnimCur { + int nelt; + AnimCurElt *elts; +} AnimCurRec, *AnimCurPtr; + +CursorBitsPtr nxagentAnimCursorBits; + +#define nxagentIsAnimCursor(c) ((c)->bits == nxagentAnimCursorBits) +#define nxagentGetAnimCursor(c) ((AnimCurPtr) ((c) + 1)) + +#define nxagentCursorPriv(pCursor, pScreen) \ + ((nxagentPrivCursor *)((pCursor)->devPriv[pScreen->myNum])) + +#define nxagentCursor(pCursor, pScreen) \ + (nxagentCursorPriv(pCursor, pScreen)->cursor) + +#define nxagentCursorPicture(pCursor, pScreen) \ + (nxagentCursorPriv(pCursor, pScreen)->picture) + +#define nxagentCursorUsesRender(pCursor, pScreen) \ + (nxagentCursorPriv(pCursor, pScreen)->uses_render) + +#define nxagentCursorXOffset(pCursor, pScreen) \ + (nxagentCursorPriv(pCursor, pScreen)->x) + +#define nxagentCursorYOffset(pCursor, pScreen) \ + (nxagentCursorPriv(pCursor, pScreen)->y) + +void nxagentConstrainCursor(ScreenPtr pScreen, BoxPtr pBox); + +void nxagentCursorLimits(ScreenPtr pScreen, CursorPtr pCursor, + BoxPtr pHotBox, BoxPtr pTopLeftBox); + +Bool nxagentDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor); + +Bool nxagentRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); + +Bool nxagentUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); + +void nxagentRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor, + Bool displayed); + +Bool nxagentSetCursorPosition(ScreenPtr pScreen, int x, int y, + Bool generateEvent); + +void nxagentDisconnectCursor(pointer p0, XID x1, pointer p2); +void nxagentReconnectCursor(pointer p0, XID x1, pointer p2); +void nxagentReDisplayCurrentCursor(void); +Bool nxagentReconnectAllCursor(void *p0); +Bool nxagentDisconnectAllCursor(void); + +#endif /* __Cursor_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Dialog.c b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c new file mode 100644 index 000000000..c1db78344 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c @@ -0,0 +1,563 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "scrnintstr.h" +#include "Agent.h" + +#include + +#include "opaque.h" + +#include "Args.h" +#include "Display.h" +#include "Dialog.h" + +#include "NX.h" +#include "NXlib.h" +#include "NXalert.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int nxagentKillDialogPid = 0; +int nxagentSuspendDialogPid = 0; +int nxagentRootlessDialogPid = 0; +int nxagentPulldownDialogPid = 0; +int nxagentFontsReplacementDialogPid = 0; +int nxagentEnableRandRModeDialogPid = 0; +int nxagentDisableRandRModeDialogPid = 0; +int nxagentEnableDeferModePid = 0; +int nxagentDisableDeferModePid = 0; +int nxagentDisableXkbPid = 0; + +static int nxagentFailedReconnectionDialogPid = 0; + +char nxagentPulldownWindow[16]; + +char nxagentFailedReconnectionMessage[256]; + +void nxagentResetDialog(int pid) +{ + if (pid == nxagentRootlessDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting rootless dialog pid [%d].\n", nxagentRootlessDialogPid); + #endif + + nxagentRootlessDialogPid = 0; + } + else if (pid == nxagentPulldownDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting pulldown dialog pid [%d].\n", nxagentPulldownDialogPid); + #endif + + nxagentPulldownDialogPid = 0; + } + else if (pid == nxagentFontsReplacementDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentFontsReplacementDialog: Resetting fonts replacement dialog pid [%d].\n", + nxagentFontsReplacementDialogPid); + #endif + + nxagentFontsReplacementDialogPid = 0; + } + else if (pid == nxagentKillDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting kill dialog pid [%d].\n", nxagentKillDialogPid); + #endif + + nxagentKillDialogPid = 0; + } + else if (pid == nxagentSuspendDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting suspend dialog pid [%d].\n", nxagentSuspendDialogPid); + #endif + + nxagentSuspendDialogPid = 0; + } + else if (pid == nxagentFailedReconnectionDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting Failed Reconnection dialog pid [%d].\n", + nxagentFailedReconnectionDialogPid); + #endif + + nxagentFailedReconnectionDialogPid = 0; + } + else if (pid == nxagentEnableRandRModeDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting RandR mode dialog pid [%d].\n", + nxagentEnableRandRModeDialogPid); + #endif + + nxagentEnableRandRModeDialogPid = 0; + } + else if (pid == nxagentDisableRandRModeDialogPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting NoRandR mode dialog pid [%d].\n", + nxagentDisableRandRModeDialogPid); + #endif + + nxagentDisableRandRModeDialogPid = 0; + } + else if (pid == nxagentEnableDeferModePid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting enable defer mode dialog pid [%d].\n", + nxagentEnableDeferModePid); + #endif + + nxagentEnableDeferModePid = 0; + } + else if (pid == nxagentDisableDeferModePid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting disable defer mode dialog pid [%d].\n", + nxagentDisableDeferModePid); + #endif + + nxagentDisableDeferModePid = 0; + } + else if (pid == nxagentDisableXkbPid) + { + #ifdef TEST + fprintf(stderr, "nxagentResetDialog: Resetting disable XKB dialog pid [%d].\n", + nxagentDisableXkbPid); + #endif + + nxagentDisableXkbPid = 0; + } +} + +void nxagentLaunchDialog(DialogType dialogType) +{ + char dialogDisplay[256]; + sigset_t set, oldSet; + int *pid; + char *type; + char *message; + int local; + const char *window = NULL; + + switch (dialogType) + { + case DIALOG_KILL_SESSION: + { + message = DIALOG_KILL_SESSION_MESSAGE; + type = DIALOG_KILL_SESSION_TYPE; + local = DIALOG_KILL_SESSION_LOCAL; + pid = &nxagentKillDialogPid; + + break; + } + case DIALOG_SUSPEND_SESSION: + { + message = DIALOG_SUSPEND_SESSION_MESSAGE; + type = DIALOG_SUSPEND_SESSION_TYPE; + local = DIALOG_SUSPEND_SESSION_LOCAL; + pid = &nxagentSuspendDialogPid; + + break; + } + case DIALOG_ROOTLESS: + { + message = DIALOG_ROOTLESS_MESSAGE; + type = DIALOG_ROOTLESS_TYPE; + local = DIALOG_ROOTLESS_LOCAL; + pid = &nxagentRootlessDialogPid; + + break; + } + case DIALOG_PULLDOWN: + { + message = DIALOG_PULLDOWN_MESSAGE; + type = DIALOG_PULLDOWN_TYPE; + local = DIALOG_PULLDOWN_LOCAL; + pid = &nxagentPulldownDialogPid; + window = nxagentPulldownWindow; + + break; + } + case DIALOG_FONT_REPLACEMENT: + { + message = DIALOG_FONT_REPLACEMENT_MESSAGE; + type = DIALOG_FONT_REPLACEMENT_TYPE; + local = DIALOG_FONT_REPLACEMENT_LOCAL; + pid = &nxagentFontsReplacementDialogPid; + + break; + } + case DIALOG_FAILED_RECONNECTION: + { + message = DIALOG_FAILED_RECONNECTION_MESSAGE; + type = DIALOG_FAILED_RECONNECTION_TYPE; + local = DIALOG_FAILED_RECONNECTION_LOCAL; + pid = &nxagentFailedReconnectionDialogPid; + + break; + } + case DIALOG_ENABLE_DESKTOP_RESIZE_MODE: + { + message = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_MESSAGE; + type = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_TYPE; + local = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_LOCAL; + pid = &nxagentEnableRandRModeDialogPid; + + break; + } + case DIALOG_DISABLE_DESKTOP_RESIZE_MODE: + { + message = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_MESSAGE; + type = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_TYPE; + local = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_LOCAL; + pid = &nxagentDisableRandRModeDialogPid; + + break; + } + case DIALOG_ENABLE_DEFER_MODE: + { + message = DIALOG_ENABLE_DEFER_MODE_MESSAGE; + type = DIALOG_ENABLE_DEFER_MODE_TYPE; + local = DIALOG_ENABLE_DEFER_MODE_LOCAL; + pid = &nxagentEnableDeferModePid; + + break; + } + case DIALOG_DISABLE_DEFER_MODE: + { + message = DIALOG_DISABLE_DEFER_MODE_MESSAGE; + type = DIALOG_DISABLE_DEFER_MODE_TYPE; + local = DIALOG_DISABLE_DEFER_MODE_LOCAL; + pid = &nxagentDisableDeferModePid; + + break; + } + case DIALOG_DISABLE_XKB: + { + message = DIALOG_DISABLE_XKB_MESSAGE; + type = DIALOG_DISABLE_XKB_TYPE; + local = DIALOG_DISABLE_XKB_LOCAL; + pid = &nxagentDisableXkbPid; + + break; + } + default: + { + #ifdef WARNING + fprintf(stderr, "nxagentLaunchDialog: Unknown Dialog type [%d].\n", dialogType); + #endif + + return; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentLaunchDialog: Launching dialog type [%d] message [%s].\n", type, message); + #endif + + if (dialogType == DIALOG_FAILED_RECONNECTION) + { + strncpy(dialogDisplay, nxagentDisplayName, 255); + } + else + { + strcpy(dialogDisplay, ":"); + strncat(dialogDisplay, display, 254); + } + + *(dialogDisplay + 255) = '\0'; + + /* + * We don't want to receive SIGCHLD + * before we store the child pid. + */ + + sigemptyset(&set); + + sigaddset(&set, SIGCHLD); + + sigprocmask(SIG_BLOCK, &set, &oldSet); + + *pid = NXTransDialog(nxagentDialogName, message, window, + type, local, dialogDisplay); + + #ifdef TEST + fprintf(stderr, "nxagentLaunchDialog: Launched dialog %s with pid [%d] on display %s.\n", + DECODE_DIALOG_TYPE(dialogType), *pid, dialogDisplay); + #endif + + *dialogDisplay = '\0'; + + /* + * Restore the previous set of + * blocked signal. + */ + + sigprocmask(SIG_SETMASK, &oldSet, NULL); +} + +void nxagentPulldownDialog(Window wid) +{ + snprintf(nxagentPulldownWindow, 15, "%ld", (long int) wid); + nxagentPulldownWindow[15] = 0; + + #ifdef TEST + fprintf(stderr, "nxagentPulldownDialog: Going to launch pulldown " + "dialog on window [%s].\n", nxagentPulldownWindow); + #endif + + nxagentLaunchDialog(DIALOG_PULLDOWN); + + nxagentPulldownWindow[0] = 0; +} + +void nxagentFailedReconnectionDialog(int alert, char *error) +{ + if (alert == 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentFailedReconnectionDialog: WARNING! No valid alert provided. " + "Using the default.\n"); + #endif + + alert = FAILED_RESUME_DISPLAY_ALERT; + } + + if (NXDisplayError(nxagentDisplay) == 0 && + NXTransRunning(NX_FD_ANY) == 1) + { + NXTransAlert(alert, NX_ALERT_REMOTE); + + /* + * Make it possible to interrupt the + * loop with a signal. + */ + + while (NXDisplayError(nxagentDisplay) == 0 && + NXTransRunning(NX_FD_ANY) == 1) + { + struct timeval timeout; + + timeout.tv_sec = 30; + timeout.tv_usec = 0; + + NXTransContinue(&timeout); + } + } + else + { + int pid; + int status; + int options = 0; + + snprintf(nxagentFailedReconnectionMessage, 255, "Reconnection failed: %s", error); + + *(nxagentFailedReconnectionMessage + 255) = '\0'; + + nxagentLaunchDialog(DIALOG_FAILED_RECONNECTION); + + while ((pid = waitpid(nxagentFailedReconnectionDialogPid, &status, options)) == -1 && + errno == EINTR); + + if (pid == -1) + { + if (errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentFailedReconnectionDialog: Got ECHILD waiting for child [%d].\n", + nxagentFailedReconnectionDialogPid); + #endif + + nxagentFailedReconnectionDialogPid = 0; + } + else + { + fprintf(stderr, "nxagentFailedReconnectionDialog: PANIC! Got unexpected error [%s] waiting " + "for child [%d].\n", strerror(errno), nxagentFailedReconnectionDialogPid); + } + } + else if (pid > 0) + { + if (WIFSTOPPED(status)) + { + #ifdef WARNING + fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] was stopped " + "with signal [%d].\n", pid, (WSTOPSIG(status))); + #endif + } + else + { + #ifdef WARNING + + if (WIFEXITED(status)) + { + fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] exited " + "with status [%d].\n", pid, (WEXITSTATUS(status))); + } + else if (WIFSIGNALED(status)) + { + fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] died " + "because of signal [%d].\n", pid, (WTERMSIG(status))); + } + + #endif + + nxagentResetDialog(pid); + } + } + #ifdef WARNING + else if (pid == 0) + { + fprintf(stderr, "nxagentFailedReconnectionDialog: No own child process exited.\n"); + } + #endif + } +} + +void nxagentTerminateDialog(DialogType type) +{ + int pid; + + switch (type) + { + case DIALOG_KILL_SESSION: + { + pid = nxagentKillDialogPid; + + break; + } + case DIALOG_SUSPEND_SESSION: + { + pid = nxagentSuspendDialogPid; + + break; + } + case DIALOG_ROOTLESS: + { + pid = nxagentRootlessDialogPid; + + break; + } + case DIALOG_PULLDOWN: + { + pid = nxagentPulldownDialogPid; + + break; + } + case DIALOG_FONT_REPLACEMENT: + { + pid = nxagentFontsReplacementDialogPid; + + break; + } + case DIALOG_FAILED_RECONNECTION: + { + pid = nxagentFailedReconnectionDialogPid; + + break; + } + case DIALOG_ENABLE_DESKTOP_RESIZE_MODE: + { + pid = nxagentEnableRandRModeDialogPid; + + break; + } + case DIALOG_DISABLE_DESKTOP_RESIZE_MODE: + { + pid = nxagentDisableRandRModeDialogPid; + + break; + } + case DIALOG_ENABLE_DEFER_MODE: + { + pid = nxagentEnableDeferModePid; + + break; + } + case DIALOG_DISABLE_DEFER_MODE: + { + pid = nxagentDisableDeferModePid; + + break; + } + case DIALOG_DISABLE_XKB: + { + pid = nxagentDisableXkbPid; + + break; + } + default: + { + #ifdef WARNING + fprintf(stderr, "nxagentTerminateDialog: Unknown dialog type [%d].\n", type); + #endif + + return; + } + } + + if (pid > 0) + { + if (kill(pid, SIGTERM) == -1) + { + #ifdef WARNING + fprintf(stderr, "nxagentTerminateDialog: Failed to terminate dialog pid [%d]: %s.\n", + pid, strerror(errno)); + #endif + } + } + #ifdef DEBUG + else + { + fprintf(stderr, "nxagentTerminateDialog: Dialog type [%d] is not running.\n", + type); + } + #endif +} + +void nxagentTerminateDialogs() +{ + DialogType type; + + #ifdef DEBUG + fprintf(stderr, "nxagentTerminateDialogs: Terminating all the running dialogs.\n"); + #endif + + for (type = DIALOG_FIRST_TAG; type < DIALOG_LAST_TAG; type++) + { + nxagentTerminateDialog(type); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Dialog.h b/nx-X11/programs/Xserver/hw/nxagent/Dialog.h new file mode 100644 index 000000000..135cd2df3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.h @@ -0,0 +1,223 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Dialog_H__ +#define __Dialog_H__ + +#include "X11/X.h" + +typedef enum +{ + DIALOG_FIRST_TAG, + DIALOG_KILL_SESSION = DIALOG_FIRST_TAG, + DIALOG_SUSPEND_SESSION, + DIALOG_ROOTLESS, + DIALOG_PULLDOWN, + DIALOG_FONT_REPLACEMENT, + DIALOG_ENABLE_DESKTOP_RESIZE_MODE, + DIALOG_DISABLE_DESKTOP_RESIZE_MODE, + DIALOG_FAILED_RECONNECTION, + DIALOG_ENABLE_DEFER_MODE, + DIALOG_DISABLE_DEFER_MODE, + DIALOG_DISABLE_XKB, + DIALOG_LAST_TAG + +} DialogType; + +extern int nxagentKillDialogPid; +extern int nxagentSuspendDialogPid; +extern int nxagentRootlessDialogPid; +extern int nxagentPulldownDialogPid; +extern int nxagentFontsReplacement; +extern int nxagentEnableRandRModeDialogPid; +extern int nxagentDisableRandRModeDialogPid; +extern int nxagentEnableDeferModePid; +extern int nxagentDisableDeferModePid; +extern int nxagentDisableXkbPid; + +extern char nxagentFailedReconnectionMessage[]; + +extern char nxagentPulldownWindow[]; + +extern void nxagentLaunchDialog(DialogType type); +extern void nxagentResetDialog(int pid); +extern void nxagentTerminateDialog(DialogType type); +extern void nxagentFailedReconnectionDialog(int alert, char *error); +extern void nxagentPulldownDialog(Window); +extern void nxagentTerminateDialogs(void); + +#define nxagentNoDialogIsRunning \ + (nxagentSuspendDialogPid == 0 && \ + nxagentKillDialogPid == 0 && \ + nxagentEnableRandRModeDialogPid == 0 && \ + nxagentDisableRandRModeDialogPid == 0 && \ + nxagentEnableDeferModePid == 0 && \ + nxagentDisableDeferModePid == 0 && \ + nxagentDisableXkbPid == 0) + +#define DECODE_DIALOG_TYPE(type) \ + ((type) == DIALOG_KILL_SESSION ? "DIALOG_KILL_SESSION" : \ + (type) == DIALOG_SUSPEND_SESSION ? "DIALOG_SUSPEND_SESSION" : \ + (type) == DIALOG_ROOTLESS ? "DIALOG_ROOTLESS" : \ + (type) == DIALOG_PULLDOWN ? "DIALOG_PULLDOWN" : \ + (type) == DIALOG_FONT_REPLACEMENT ? "DIALOG_FONT_REPLACEMENT" : \ + (type) == DIALOG_ENABLE_DESKTOP_RESIZE_MODE ? "DIALOG_ENABLE_DESKTOP_RESIZE_MODE" :\ + (type) == DIALOG_DISABLE_DESKTOP_RESIZE_MODE ? "DIALOG_DISABLE_DESKTOP_RESIZE_MODE" :\ + (type) == DIALOG_FAILED_RECONNECTION ? "DIALOG_FAILED_RECONNECTION" : \ + (type) == DIALOG_ENABLE_DEFER_MODE ? "DIALOG_ENABLE_DEFER_MODE" : \ + (type) == DIALOG_DISABLE_DEFER_MODE ? "DIALOG_DISABLE_DEFER_MODE" : \ + (type) == DIALOG_DISABLE_XKB ? "DIALOG_DISABLE_XKB" : \ + "UNKNOWN_DIALOG") + +/* + * Message to be showed to users when the close + * button is pressed. The right message is chosen + * according if session does or does not run in + * persistent mode. + */ + +#define DIALOG_KILL_SESSION_MESSAGE \ +\ +"\ +Do you really want to close the session?\ +" + +#define DIALOG_KILL_SESSION_TYPE "yesno" + +#define DIALOG_KILL_SESSION_LOCAL 0 + + +#define DIALOG_SUSPEND_SESSION_MESSAGE \ +\ +"\ +Press the disconnect button to disconnect the running session.\n\ +You will be able to resume the session at later time. Press the\n\ +terminate button to exit the session and close all the running\n\ +programs.\ +" + +#define DIALOG_SUSPEND_SESSION_TYPE "yesnosuspend" + +#define DIALOG_SUSPEND_SESSION_LOCAL 0 + + +#define DIALOG_ROOTLESS_MESSAGE \ +\ +"\ +All remote applications have been terminated.\n\ +Do you want to close the session?\ +" + +#define DIALOG_ROOTLESS_TYPE "yesno" + +#define DIALOG_ROOTLESS_LOCAL 0 + + +#define DIALOG_PULLDOWN_MESSAGE \ +\ +nxagentPulldownWindow + +#define DIALOG_PULLDOWN_TYPE "pulldown" + +#define DIALOG_PULLDOWN_LOCAL 0 + + +#define DIALOG_FONT_REPLACEMENT_MESSAGE \ +\ +"\ +Unable to retrieve all the fonts currently in use. \n\ +Missing fonts have been replaced.\ +" + +#define DIALOG_FONT_REPLACEMENT_TYPE "ok" + +#define DIALOG_FONT_REPLACEMENT_LOCAL 0 + + +#define DIALOG_FAILED_RECONNECTION_MESSAGE \ +\ +nxagentFailedReconnectionMessage + +#define DIALOG_FAILED_RECONNECTION_TYPE "ok" + +#define DIALOG_FAILED_RECONNECTION_LOCAL 0 + + +#define DIALOG_ENABLE_DESKTOP_RESIZE_MODE_MESSAGE \ +\ +"\ +The session is now running in desktop resize mode.\n\ +You can resize the desktop by simply dragging the\n\ +desktop window's border. You can press Ctrl+Alt+R\n\ +again to disable this option.\ +" + +#define DIALOG_ENABLE_DESKTOP_RESIZE_MODE_TYPE "ok" + +#define DIALOG_ENABLE_DESKTOP_RESIZE_MODE_LOCAL 0 + +#define DIALOG_DISABLE_DESKTOP_RESIZE_MODE_MESSAGE \ +\ +"\ +The session is now running in viewport mode. You can\n\ +navigate across different areas of the desktop window\n\ +by dragging the desktop with the mouse or by using the\n\ +arrows keys while pressing Ctrl+Alt. Press Ctrl+Alt+R\n\ +again to return to the desktop resize mode.\ +" + +#define DIALOG_DISABLE_DESKTOP_RESIZE_MODE_TYPE "ok" + +#define DIALOG_DISABLE_DESKTOP_RESIZE_MODE_LOCAL 0 + + +#define DIALOG_ENABLE_DEFER_MODE_MESSAGE \ +\ +"\ +Deferred screen updates are now enabled. You can press\n\ +Ctrl+Alt+E again to disable this option.\ +" + +#define DIALOG_ENABLE_DEFER_MODE_TYPE "ok" + +#define DIALOG_ENABLE_DEFER_MODE_LOCAL 0 + + +#define DIALOG_DISABLE_DEFER_MODE_MESSAGE \ +\ +"\ +Deferred screen updates are now disabled. You can press\n\ +Ctrl+Alt+E to enable it again.\ +" + +#define DIALOG_DISABLE_DEFER_MODE_TYPE "ok" + +#define DIALOG_DISABLE_DEFER_MODE_LOCAL 0 + + +#define DIALOG_DISABLE_XKB_MESSAGE \ +\ +"\ +Changing layout is not allowed with your current display.\ +" + +#define DIALOG_DISABLE_XKB_TYPE "ok" + +#define DIALOG_DISABLE_XKB_LOCAL 0 + +#endif /* __Dialog_H__ */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Display.c b/nx-X11/programs/Xserver/hw/nxagent/Display.c new file mode 100644 index 000000000..c2e131954 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Display.c @@ -0,0 +1,2705 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "windowstr.h" +#include "dixstruct.h" + +#ifdef WATCH +#include "unistd.h" +#endif + +#include "NXalert.h" + +#include "Agent.h" +#include "Display.h" +#include "Visual.h" +#include "Options.h" +#include "Error.h" +#include "Init.h" +#include "Args.h" +#include "Image.h" +#include "Icons.h" +#include "Render.h" +#include "Font.h" +#include "Reconnect.h" +#include "Events.h" +#include "Dialog.h" +#include "Client.h" +#include "Splash.h" +#include "Screen.h" +#include "Handlers.h" + +#include "NX.h" +#include "NXlib.h" + +#include NXAGENT_ICON_NAME + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef WATCH + +Display *nxagentDisplay = NULL; +XVisualInfo *nxagentVisuals = NULL; +Bool nxagentTrue24 = False; + +int nxagentNumVisuals; +int nxagentXConnectionNumber; + +int nxagentIOErrorHandler(Display *display); + +static Bool nxagentDisplayInfoSaved = False; +static Display *nxagentDisplayBackup = NULL; +static XlibGC nxagentBitmapGCBackup = NULL; +static XVisualInfo *nxagentVisualsRecBackup; +static int nxagentNumVisualsRecBackup; +static int nxagentNumDefaultColormapsRecBackup; +static int *nxagentDepthsRecBackup; +static int nxagentNumDepthsRecBackup; +static int nxagentDefaultDepthRecBackup; +static int nxagentDisplayWidthRecBackup; +static int nxagentDisplayHeightRecBackup; +static Bool nxagentRenderEnableRecBackup; +static Bool *nxagentVisualHasBeenIgnored; + +static enum +{ + NOTHING = 0, + OPENED, + GOT_VISUAL_INFO, + ALLOC_DEF_COLORMAP, + GOT_DEPTH_LIST, + GOT_PIXMAP_FORMAT_LIST, + EVERYTHING_DONE +} reconnectDisplayState; + +int nxagentDefaultVisualIndex; +Colormap *nxagentDefaultColormaps; +int nxagentNumDefaultColormaps; +int *nxagentDepths; +int nxagentNumDepths; +XPixmapFormatValues *nxagentPixmapFormats; +XPixmapFormatValues *nxagentRemotePixmapFormats; +int nxagentNumPixmapFormats; +int nxagentRemoteNumPixmapFormats; +Pixel nxagentBlackPixel; +Pixel nxagentWhitePixel; +Drawable nxagentDefaultDrawables[MAXDEPTH + 1]; +Pixmap nxagentScreenSaverPixmap; + +/* + * Also used in Cursor.c. There are huge problems + * using GC definition. This is to be reworked. + */ + +XlibGC nxagentBitmapGC; + +/* + * The "confine" window is used in the nxagentConstrainCursor + * procedure. We are currently overriding the original Xnest + * behaviour. It is unclear what this window is used for. + */ + +Window nxagentConfineWindow; + +Pixmap nxagentIconPixmap; +Pixmap nxagentIconShape; +Bool useXpmIcon = False; + +unsigned int nxagentLogoColor(unsigned int value); +Bool nxagentMakeIcon(Display *display, Pixmap *nxIcon, Pixmap *nxMask); + + +static void nxagentInitVisuals(void); +static void nxagentSetDefaultVisual(void); +static void nxagentInitDepths(void); +static void nxagentInitPixmapFormats(void); + +static int nxagentCheckForDefaultDepthCompatibility(void); +static int nxagentCheckForDepthsCompatibility(int flexibility); +static int nxagentCheckForPixmapFormatsCompatibility(void); +static int nxagentInitAndCheckVisuals(int flexibility); +static int nxagentCheckForColormapsCompatibility(int flexibility); + +/* + * FIXME: These must definitely become local. + */ + +XVisualInfo pV; +unsigned int r, b, g, or, ob, og, off; + +/* + * Save Internal implementation Also called in Reconnect.c. + */ + +Display *nxagentInternalOpenDisplay(char *display); + +#ifdef NXAGENT_TIMESTAMP +unsigned long startTime; +#endif + +/* + * This is located in connection.c. + */ + +extern void RejectWellKnownSockets(void); + +int nxagentServerOrder() +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + + return MSBFirst; +} + +unsigned int nxagentLogoColor(unsigned int value) +{ + /* + * Takes a color value in RGB24 (0xff0000, 0x00ff00, + * 0x0000ff) and converts it into an equivalent for + * the current visual. + */ + + int cr=0, cg=0, cb=0; + + cr = (value >> or) &r; + cg = (value >> (og - 8)) &g; + cb = (value >> (ob - 16)) &b; + + return (cr | cg | cb); +} + +/* + * FIXME: This error handler is not printing anything + * in the session log. This is OK once the session is + * started, because the error is handled by the other + * layers, but not before that point, as the agent + * would die without giving any feedback to the user + * (or, worse, to the NX server). We should check how + * many requests have been handled for this display + * and print a message if the display dies before the + * session is up and running. + */ + +/* + * FIXME: This should be moved to Error.c, The other + * handlers should be probably moved to Handlers.c. + */ + +int nxagentIOErrorHandler(Display *display) +{ + #ifdef TEST + fprintf(stderr, "nxagentIOErrorHandler: Got I/O error with nxagentException.ioError [%d].\n", + nxagentException.ioError); + #endif + + nxagentException.ioError++; + + #ifdef TEST + fprintf(stderr, "nxagentIOErrorHandler: Set nxagentException.ioError to [%d].\n", + nxagentException.ioError); + #endif + + return 1; +} + +/* + * Force a shutdown of any connection attempt + * while connecting to the remote display. + * This is needed to avoid a hang up in case + * of loopback connections to our own listen- + * ing sockets. + */ + +static void nxagentRejectConnection(int signal) +{ + #ifdef TEST + fprintf(stderr, "nxagentRejectConnection: Going to reject client connections.\n"); + #endif + + RejectWellKnownSockets(); + + #ifdef TEST + fprintf(stderr, "nxagentRejectConnection: Setting new alarm to 5 seconds from now.\n"); + #endif + + /* + * A further timeout is unlikely to happen + * in the case of loopback connections. + */ + + alarm(5); +} + +/* + * Ignore the signal if the NX transport is + * not running. + */ + +static void nxagentSigusrHandler(int signal) +{ + #ifdef TEST + fprintf(stderr, "nxagentSigusrHandler: Nothing to do with signal [%d].\n", + signal); + #endif +} + +static void nxagentSighupHandler(int signal) +{ + #ifdef TEST + fprintf(stderr, "nxagentSighupHandler: Handling signal with state [%s] transport [%d] server " + "generation [%ld].\n", DECODE_SESSION_STATE(nxagentSessionState), + NXTransRunning(NX_FD_ANY), serverGeneration); + #endif + + if (signal != SIGHUP) + { + #ifdef PANIC + fprintf(stderr, "nxagentSighupHandler: PANIC! Invalid signal [%d] received in state [%s].\n", + signal, DECODE_SESSION_STATE(nxagentSessionState)); + #endif + + return; + } + + if (dispatchException & DE_TERMINATE) + { + #ifdef TEST + fprintf(stderr, "nxagentSighupHandler: Ignoring the signal while terminating the session.\n"); + #endif + + return; + } + else if (nxagentSessionState == SESSION_UP) + { + if (nxagentOption(Persistent) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSighupHandler: Handling the signal by disconnecting the agent.\n"); + #endif + + nxagentException.sigHup++; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentSighupHandler: Ignoring the signal with persistency disabled.\n"); + #endif + } + + return; + } + else if (nxagentSessionState == SESSION_STARTING) + { + #ifdef TEST + fprintf(stderr, "nxagentSighupHandler: Handling the signal by aborting the session.\n"); + #endif + + nxagentException.sigHup++; + + return; + } + else if (nxagentSessionState == SESSION_DOWN) + { + if (NXTransRunning(NX_FD_ANY) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSighupHandler: Handling the signal by aborting the reconnection.\n"); + #endif + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentSighupHandler: Handling the signal by resuming the session.\n"); + #endif + } + + nxagentException.sigHup++; + + return; + } + + #ifdef WARNING + fprintf(stderr, "nxagentSighupHandler: WARNING! Ignoring the signal in state [%s].\n", + DECODE_SESSION_STATE(nxagentSessionState)); + #endif +} + +static void nxagentSigchldHandler(int signal) +{ + int pid = 0; + int status; + int options; + + #ifdef TEST + fprintf(stderr, "nxagentSigchldHandler: Going to check the children processes.\n"); + #endif + + options = WNOHANG | WUNTRACED; + + /* + * Try with the pid of the dialog process. + * Leave the other children unaffected. + */ + + if (pid == 0 && nxagentRootlessDialogPid) + { + pid = waitpid(nxagentRootlessDialogPid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Rootless dialog).\n", + nxagentRootlessDialogPid); + #endif + + pid = nxagentRootlessDialogPid = 0; + } + } + + if (pid == 0 && nxagentPulldownDialogPid) + { + pid = waitpid(nxagentPulldownDialogPid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Pulldown dialog).\n", + nxagentPulldownDialogPid); + #endif + + pid = nxagentPulldownDialogPid = 0; + } + } + + if (pid == 0 && nxagentKillDialogPid) + { + pid = waitpid(nxagentKillDialogPid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Kill dialog).\n", + nxagentKillDialogPid); + #endif + + pid = nxagentKillDialogPid = 0; + } + } + + if (pid == 0 && nxagentSuspendDialogPid) + { + pid = waitpid(nxagentSuspendDialogPid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Suspend dialog).\n", + nxagentSuspendDialogPid); + #endif + + pid = nxagentSuspendDialogPid = 0; + } + } + + if (pid == 0 && nxagentEnableRandRModeDialogPid) + { + pid = waitpid(nxagentEnableRandRModeDialogPid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (EnableRandRMode dialog).\n", + nxagentEnableRandRModeDialogPid); + #endif + + pid = nxagentEnableRandRModeDialogPid = 0; + } + } + + if (pid == 0 && nxagentDisableRandRModeDialogPid) + { + pid = waitpid(nxagentDisableRandRModeDialogPid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (DisableRandRMode dialog).\n", + nxagentDisableRandRModeDialogPid); + #endif + + pid = nxagentDisableRandRModeDialogPid = 0; + } + } + + if (pid == 0 && nxagentEnableDeferModePid) + { + pid = waitpid(nxagentEnableDeferModePid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (EnableDeferMode dialog).\n", + nxagentEnableDeferModePid); + #endif + + pid = nxagentEnableDeferModePid = 0; + } + } + + if (pid == 0 && nxagentDisableDeferModePid) + { + pid = waitpid(nxagentDisableDeferModePid, &status, options); + + if (pid == -1 && errno == ECHILD) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (DisableDeferMode dialog).\n", + nxagentDisableDeferModePid); + #endif + + pid = nxagentDisableDeferModePid = 0; + } + } + + if (pid == -1) + { + FatalError("Got error '%s' waiting for the child.\n", strerror(errno)); + } + + if (pid > 0) + { + if (WIFSTOPPED(status)) + { + #ifdef WARNING + fprintf(stderr, "nxagentSigchldHandler: Child process [%d] was stopped " + "with signal [%d].\n", pid, (WSTOPSIG(status))); + #endif + } + else + { + #ifdef TEST + + if (WIFEXITED(status)) + { + fprintf(stderr, "nxagentSigchldHandler: Child process [%d] exited " + "with status [%d].\n", pid, (WEXITSTATUS(status))); + } + else if (WIFSIGNALED(status)) + { + fprintf(stderr, "nxagentSigchldHandler: Child process [%d] died " + "because of signal [%d].\n", pid, (WTERMSIG(status))); + } + + #endif + + nxagentResetDialog(pid); + } + } + else if (pid == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSigchldHandler: Forwarding the signal to the NX transport.\n"); + #endif + + NXTransSignal(SIGCHLD, NX_SIGNAL_RAISE); + } + + return; +} + +Display *nxagentInternalOpenDisplay(char *display) +{ + Display *newDisplay; + + struct sigaction oldAction; + struct sigaction newAction; + + int result; + + #ifdef SMART_SCHEDULE + + /* + * Stop the smart schedule timer since + * it uses SIGALRM as we do. + */ + + nxagentStopTimer(); + + #endif + + /* + * Install the handler rejecting a possible + * loopback connection. + */ +/* +FIXME: Should print a warning if the user tries to let + the agent impersonate the same display as the + display where the agent is supposed to connect. + We actually handle this by means of RejectWell- + KnownSockets() but without giving to the user + a friendly explaination for the error. +*/ + + newAction.sa_handler = nxagentRejectConnection; + + sigfillset(&newAction.sa_mask); + + newAction.sa_flags = 0; + + while (((result = sigaction(SIGALRM, &newAction, + &oldAction)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't set alarm for rejecting connections."); + } + + alarm(10); + + #ifdef TEST + fprintf(stderr, "nxagentInternalOpenDisplay: Going to open the display [%s].\n", + display); + #endif + + newDisplay = XOpenDisplay(display); + + alarm(0); + + while (((result = sigaction(SIGALRM, &oldAction, + NULL)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't restore alarm for rejecting connections."); + } + + #ifdef TEST + fprintf(stderr, "nxagentInternalOpenDisplay: Setting the NX flush policy to immediate.\n"); + #endif + + NXSetDisplayPolicy(nxagentDisplay, NXPolicyImmediate); + + #ifdef TEST + fprintf(stderr, "nxagentInternalOpenDisplay: Function returned display at [%p].\n", + (void *) newDisplay); + #endif + + return newDisplay; +} + +static void nxagentDisplayBlockHandler(Display *display, int reason) +{ + if (nxagentDisplay != NULL) + { + /* + * Don't allow the smart schedule to + * interrupt the agent while waiting + * for the remote display. + */ + + #ifdef SMART_SCHEDULE + + #ifdef DEBUG + fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Stopping the smart schedule timer.\n"); + #endif + + nxagentStopTimer(); + + #endif + + if (reason == NXBlockRead) + { + #ifdef DEBUG + fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Display is blocking for [read].\n"); + #endif + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Display is blocking for [write].\n"); + #endif + + nxagentBlocking = 1; + + #ifdef SMART_SCHEDULE + + if (SmartScheduleDisable == 1) + { + + #endif + + /* + * Let the dispatch attend the next + * client. + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Yielding with agent blocked.\n"); + #endif + + nxagentDispatch.start = GetTimeInMillis(); + + nxagentDispatch.in = nxagentBytesIn; + nxagentDispatch.out = nxagentBytesOut; + + #ifdef SMART_SCHEDULE + + } + + #endif + + /* + * Give a chance to the next client. + */ + + isItTimeToYield = 1; + } + } +} + +static void nxagentDisplayWriteHandler(Display *display, int length) +{ + if (nxagentDisplay != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentDisplayWriteHandler: WRITE! Called with [%d] bytes written.\n", + length); + #endif + + /* + * Notify the dispatch handler. + */ + + nxagentDispatchHandler(NULL, 0, length); + + if (nxagentOption(LinkType) == LINK_TYPE_NONE) + { + nxagentFlush = GetTimeInMillis(); + } + } +} + +static void nxagentDisplayFlushHandler(Display *display, int length) +{ + if (nxagentDisplay != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentDisplayFlushHandler: FLUSH! Called with [%d] bytes flushed.\n", + length); + #endif + + nxagentCongestion = NXDisplayCongestion(nxagentDisplay); + + #ifdef TEST + fprintf(stderr, "nxagentDisplayFlushHandler: FLUSH! Current congestion level is [%d].\n", + nxagentCongestion); + #endif + + if (nxagentOption(LinkType) != LINK_TYPE_NONE) + { + nxagentFlush = GetTimeInMillis(); + } + } +} + +static int nxagentDisplayErrorPredicate(Display *display, int error) +{ + #ifdef TEST + fprintf(stderr, "nxagentDisplayErrorPredicate: CHECK! Error is [%d] with [%d][%d][%d][%d][%d].\n", + ((error == 1) || (dispatchException & DE_RESET) != 0 || + (dispatchException & DE_TERMINATE) != 0 || nxagentException.sigHup > 0 || + nxagentException.ioError > 0), error, (dispatchException & DE_RESET) != 0, + (dispatchException & DE_TERMINATE), nxagentException.sigHup > 0, + nxagentException.ioError > 0); + #endif + + if (error == 0) + { + if ((dispatchException & DE_RESET) != 0 || + (dispatchException & DE_TERMINATE)) + { + return 1; + } + else if (nxagentException.sigHup > 0 || + nxagentException.ioError > 0) + { + NXForceDisplayError(display); + + return 1; + } + } + + return error; +} + +void nxagentInstallDisplayHandlers() +{ + /* + * If the display was already opened, be sure + * all structures are freed. + */ + + nxagentResetDisplayHandlers(); + + /* + * We want the Xlib I/O error handler to return, + * instead of quitting the application. Using + * setjmp()/longjmp() leaves the door open to + * unexpected bugs when dealing with interaction + * with the other X server layers. + */ + + NXHandleDisplayError(1); + + NXSetDisplayBlockHandler(nxagentDisplayBlockHandler); + + NXSetDisplayWriteHandler(nxagentDisplayWriteHandler); + + NXSetDisplayFlushHandler(nxagentDisplayFlushHandler, NULL); + + /* + * Override the default Xlib error handler. + */ + + XSetIOErrorHandler(nxagentIOErrorHandler); + + /* + * Let Xlib become aware of our interrupts. In theory + * we don't need to have the error handler installed + * during the normal operations and could simply let + * the dispatcher handle the interrupts. In practice + * it's better to have Xlib invalidating the display + * as soon as possible rather than incurring in the + * risk of entering a loop that doesn't care checking + * the display errors explicitly. + */ + + #ifdef TEST + fprintf(stderr, "nxagentInstallDisplayHandlers: Installing the error function predicate.\n"); + #endif + + NXSetDisplayErrorPredicate(nxagentDisplayErrorPredicate); +} + +void nxagentPostInstallDisplayHandlers() +{ + /* + * This is executed after having opened the + * display, once we know the display address. + */ + + if (nxagentDisplay != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentPostInstallDisplayHandlers: Initializing the NX display internals.\n"); + #endif + + NXInitDisplay(nxagentDisplay); +/* +FIXME: What is the most appropriate number of elements? + + NXInitCache(nxagentDisplay, 128); +*/ + NXInitCache(nxagentDisplay, 256); + + NXSetDisplayFlushHandler(nxagentDisplayFlushHandler, nxagentDisplay); + } + + /* + * Handler for the Xlib protocol errors. + */ + + XSetErrorHandler(nxagentErrorHandler); +} + +void nxagentResetDisplayHandlers() +{ + if (nxagentDisplay != NULL) + { + /* + * Free the internal nxcompext + * structures. + */ + + NXResetDisplay(nxagentDisplay); + + /* + * Remove the display descriptor + * from the listened sockets. + */ + + nxagentRemoveXConnection(); + + /* + * Restart the suspended clients. + */ + + nxagentWakeupByReconnect(); + + nxagentReleaseAllSplits(); + } + + /* + * Reset the display to a healty state. + */ + + nxagentBuffer = 0; + nxagentBlocking = 0; + nxagentCongestion = 0; + + /* + * Reset the counter of synchronization + * requests pending. + */ + + nxagentTokens.soft = 0; + nxagentTokens.hard = 0; + nxagentTokens.pending = 0; + + /* + * Reset the current dispatch information. + */ + + nxagentDispatch.client = UNDEFINED; + nxagentDispatch.in = 0; + nxagentDispatch.out = 0; + nxagentDispatch.start = 0; +} + +void nxagentInstallSignalHandlers() +{ + #ifdef TEST + fprintf(stderr, "nxagentInstallSignalHandlers: Installing the agent signal handlers.\n"); + #endif + + /* + * Keep the default X server's handlers for + * SIGINT and SIGTERM and restore the other + * signals of interest to our defaults. + */ + + struct sigaction newAction; + + int result; + + /* + * By default nxcomp installs its signal handlers. + * We need to ensure that SIGUSR1 and SIGUSR2 are + * ignored if the NX transport is not running. + */ + + newAction.sa_handler = nxagentSigusrHandler; + + sigfillset(&newAction.sa_mask); + + newAction.sa_flags = 0; + + while (((result = sigaction(SIGUSR1, &newAction, + NULL)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't set the handler for user signal 1."); + } + + while (((result = sigaction(SIGUSR2, &newAction, + NULL)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't set the handler for user signal 2."); + } + + /* + * Reset the SIGALRM to the default. + */ + + #ifdef SMART_SCHEDULE + + nxagentStopTimer(); + + #endif + + newAction.sa_handler = SIG_DFL; + + sigfillset(&newAction.sa_mask); + + while (((result = sigaction(SIGALRM, &newAction, + NULL)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't set the handler for alarm signal."); + } + + #ifdef SMART_SCHEDULE + + /* + * Let the smart schedule set the SIGALRM + * handler again. + */ + + nxagentInitTimer(); + + #endif + + /* + * Install our own handler for the SIGHUP. + */ + + newAction.sa_handler = nxagentSighupHandler; + + sigfillset(&newAction.sa_mask); + + newAction.sa_flags = 0; + + while (((result = sigaction(SIGHUP, &newAction, + NULL)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't set the handler for session suspend."); + } + + /* + * We need to be notified about our children. + */ + + newAction.sa_handler = nxagentSigchldHandler; + + sigfillset(&newAction.sa_mask); + + newAction.sa_flags = 0; + + while (((result = sigaction(SIGCHLD, &newAction, + NULL)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't set the handler for children."); + } +} + +void nxagentPostInstallSignalHandlers() +{ + #ifdef TEST + fprintf(stderr, "nxagentPostInstallSignalHandlers: Dealing with the proxy signal handlers.\n"); + #endif + + /* + * Reconfigure our signal handlers to work well + * with the NX transport. + * + * Let our handlers manage the SIGINT and SIGTERM. + * The following calls will tell the NX transport + * to restore the old handlers (those originally + * installed by us or the X server). + */ + + NXTransSignal(SIGINT, NX_SIGNAL_DISABLE); + NXTransSignal(SIGTERM, NX_SIGNAL_DISABLE); + + /* + * Also tell the proxy to ignore the SIGHUP. + */ + + NXTransSignal(SIGHUP, NX_SIGNAL_DISABLE); + + /* + * Both the proxy and the agent need to catch + * their children, so we'll have to send the + * signal to transport. + */ + + NXTransSignal(SIGCHLD, NX_SIGNAL_DISABLE); + + /* + * Let the NX transport take care of SIGUSR1 + * and SIGUSR2. + */ +} + +void nxagentResetSignalHandlers() +{ + struct sigaction newAction; + + int result; + + /* + * Reset the signal handlers + * to a well known state. + */ + + #ifdef TEST + fprintf(stderr, "nxagentResetSignalHandlers: Resetting the agent the signal handlers.\n"); + #endif + + /* + * Reset the SIGALRM to the default. + */ + + #ifdef SMART_SCHEDULE + + nxagentStopTimer(); + + #endif + + newAction.sa_handler = SIG_DFL; + + sigfillset(&newAction.sa_mask); + + while (((result = sigaction(SIGALRM, &newAction, + NULL)) == -1) && (errno == EINTR)); + + if (result == -1) + { + FatalError("Can't set the handler for alarm signal."); + } + + #ifdef SMART_SCHEDULE + + /* + * Let the smart schedule set the SIGALRM + * handler again. + */ + + nxagentInitTimer(); + + #endif +} + +void nxagentOpenDisplay(int argc, char *argv[]) +{ + int i; + + if (!nxagentDoFullGeneration) return; + + #ifdef NXAGENT_TIMESTAMP + + startTime = GetTimeInMillis(); + + fprintf(stderr, "Display: Opening the display on real X server with time [%d] ms.\n", + GetTimeInMillis() - startTime); + + #endif + + /* + * Initialize the reconnector only in the case + * of persistent sessions. + */ + + if (nxagentOption(Persistent)) + { + nxagentInitReconnector(); + } + + if (*nxagentDisplayName == '\0') + { + strncpy(nxagentDisplayName, XDisplayName(NULL), 1023); + + nxagentDisplayName[1023] = '\0'; + } + + nxagentCloseDisplay(); + + nxagentInstallSignalHandlers(); + + nxagentInstallDisplayHandlers(); + + nxagentDisplay = nxagentInternalOpenDisplay(nxagentDisplayName); + + nxagentPostInstallSignalHandlers(); + + nxagentPostInstallDisplayHandlers(); + + if (nxagentDisplay == NULL) + { +/* +FIXME: The agent should never exit the program with a FatalError() + but rather use a specific function that may eventually call + FatalError() on its turn. +*/ + FatalError("Unable to open display '%s'.\n", nxagentDisplayName); + } + + nxagentXConnectionNumber = XConnectionNumber(nxagentDisplay); + + #ifdef TEST + fprintf(stderr, "nxagentOpenDisplay: Display image order is [%d] bitmap order is [%d].\n", + ImageByteOrder(nxagentDisplay), BitmapBitOrder(nxagentDisplay)); + + fprintf(stderr, "nxagentOpenDisplay: Display scanline unit is [%d] scanline pad is [%d].\n", + BitmapUnit(nxagentDisplay), BitmapPad(nxagentDisplay)); + #endif + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenDisplay: Watchpoint 1.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#1 U 1 1 256 bits (0 KB) -> 150 bits (0 KB) -> 256/1 -> 150/1 = 1.707:1 +#20 1 1 119104 bits (15 KB) -> 28 bits (0 KB) -> 119104/1 -> 28/1 = 4253.714:1 +#98 2 512 bits (0 KB) -> 84 bits (0 KB) -> 256/1 -> 42/1 = 6.095:1 +*/ + + sleep(60); + + #endif + + #ifdef NXAGENT_TIMESTAMP + + fprintf(stderr, "Display: Display on real X server opened with time [%d] ms.\n", + GetTimeInMillis() - startTime); + + #endif + + nxagentUseNXTrans = + nxagentPostProcessArgs(nxagentDisplayName, nxagentDisplay, + DefaultScreenOfDisplay(nxagentDisplay)); + + /* + * Processing the arguments all the timeouts + * have been set. Now we have to change the + * screen-saver timeout. + */ + + nxagentSetScreenSaverTime(); + + nxagentInitVisuals(); + + nxagentNumDefaultColormaps = nxagentNumVisuals; + nxagentDefaultColormaps = (Colormap *)xalloc(nxagentNumDefaultColormaps * + sizeof(Colormap)); + + for (i = 0; i < nxagentNumDefaultColormaps; i++) + { + nxagentDefaultColormaps[i] = XCreateColormap(nxagentDisplay, + DefaultRootWindow(nxagentDisplay), + nxagentVisuals[i].visual, + AllocNone); + } + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenDisplay: Watchpoint 4.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +N/A +*/ + + sleep(30); + + #endif + + nxagentBlackPixel = BlackPixel(nxagentDisplay, DefaultScreen(nxagentDisplay)); + nxagentWhitePixel = WhitePixel(nxagentDisplay, DefaultScreen(nxagentDisplay)); + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenDisplay: Watchpoint 5.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +N/A +*/ + + sleep(30); + + #endif + + /* + * Initialize the agent's event mask that will be requested + * for the root and all the top level windows. If the nested + * window is a child of an existing window, we will need to + * receive StructureNotify events. If we are going to manage + * the changes in root window's visibility we'll also need + * VisibilityChange events. + */ + +/* +FIXME: Use of nxagentParentWindow is strongly deprecated. + We need also to clarify which events are selected + in the diferent operating modes. +*/ + + nxagentInitDefaultEventMask(); + + /* + * Initialize the pixmap depths and formats. + */ + + nxagentInitDepths(); + + nxagentInitPixmapFormats(); + + /* + * Create a pixmap for each depth matching the + * local supported formats with format available + * on the remote display. + */ + + nxagentSetDefaultDrawables(); + + #ifdef RENDER + if (nxagentRenderEnable) + { + nxagentRenderExtensionInit(); + } + #endif + + /* + * This GC is referenced in Cursor.c. It can be + * probably removed. + */ + + nxagentBitmapGC = XCreateGC(nxagentDisplay, nxagentDefaultDrawables[1], 0L, NULL); + + /* + * Note that this "confine window" is useless at the + * moment as we reimplement nxagentConstrainCursor() + * to skip the "constrain" stuff. + */ + + #ifdef TEST + fprintf(stderr, "nxagentOpenDisplay: Going to create agent's confine window.\n"); + #endif + + nxagentConfineWindow = XCreateWindow(nxagentDisplay, + DefaultRootWindow(nxagentDisplay), + 0, 0, 1, 1, 0, 0, + InputOnly, + CopyFromParent, + 0L, NULL); + + #ifdef TEST + fprintf(stderr, "nxagentOpenDisplay: Created agent's confine window with id [%ld].\n", + nxagentConfineWindow); + #endif + + if (!(nxagentUserGeometry.flag & XValue)) + { + nxagentChangeOption(RootX, 0); + } + + if (!(nxagentUserGeometry.flag & YValue)) + { + nxagentChangeOption(RootY, 0); + } + + if (nxagentParentWindow == 0) + { + if (!(nxagentUserGeometry.flag & WidthValue)) + { + if (nxagentOption(Fullscreen)) + { + nxagentChangeOption(RootWidth, DisplayWidth(nxagentDisplay, DefaultScreen(nxagentDisplay))); + } + else + { + nxagentChangeOption(RootWidth, 3 * DisplayWidth(nxagentDisplay, + DefaultScreen(nxagentDisplay)) / 4); + } + } + + if (!(nxagentUserGeometry.flag & HeightValue)) + { + if (nxagentOption(Fullscreen)) + { + nxagentChangeOption(RootHeight, DisplayHeight(nxagentDisplay, DefaultScreen(nxagentDisplay))); + } + else + { + nxagentChangeOption(RootHeight, 3 * DisplayHeight(nxagentDisplay, + DefaultScreen(nxagentDisplay)) / 4); + } + } + } + + if (!nxagentUserBorderWidth) + { + nxagentChangeOption(BorderWidth, 1); + } + + nxagentLogoDepth = DefaultDepth(nxagentDisplay, + DefaultScreen(nxagentDisplay) + ); + + pV = nxagentVisuals[nxagentDefaultVisualIndex]; + + r = pV.red_mask; + g = pV.green_mask; + b = pV.blue_mask; + + if (!pV.red_mask || !pV.green_mask || !pV.blue_mask) + { + nxagentLogoBlack = 0x000000; + nxagentLogoRed = 0xff0000; + nxagentLogoWhite = 0xffffff; + } + else + { + for (or=0, off=0x800000; (r&(off>>or)) == 0; or++); + for (og=0, off=0x800000; (g&(off>>og)) == 0; og++); + for (ob=0, off=0x800000; (b&(off>>ob)) == 0; ob++); + + nxagentLogoRed = nxagentLogoColor(0xff0000); + nxagentLogoBlack = nxagentLogoColor(0x000000); + nxagentLogoWhite = 0xffffff; + } + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenDisplay: Watchpoint 5.1.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +N/A +*/ + + sleep(30); + + #endif + + useXpmIcon = nxagentMakeIcon(nxagentDisplay, &nxagentIconPixmap, &nxagentIconShape); + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenDisplay: Watchpoint 5.2.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#84 2 512 bits (0 KB) -> 76 bits (0 KB) -> 256/1 -> 38/1 = 6.737:1 +*/ + + sleep(30); + + #endif + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenDisplay: Watchpoint 6.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +N/A +*/ + + sleep(30); + + #endif + + #ifdef NXAGENT_TIMESTAMP + + fprintf(stderr, "Display: Open of the display finished with time [%d] ms.\n", + GetTimeInMillis() - startTime); + + #endif + + if (nxagentOption(Persistent)) + { + reconnectDisplayState = EVERYTHING_DONE; + } +} + +void nxagentSetDefaultVisual(void) +{ + XVisualInfo vi; + + int i; + + if (nxagentUserDefaultClass || nxagentUserDefaultDepth) + { + nxagentDefaultVisualIndex = UNDEFINED; + + for (i = 0; i < nxagentNumVisuals; i++) + { + if ((!nxagentUserDefaultClass || + nxagentVisuals[i].class == nxagentDefaultClass) + && + (!nxagentUserDefaultDepth || + nxagentVisuals[i].depth == nxagentDefaultDepth)) + { + nxagentDefaultVisualIndex = i; + + break; + } + } + + if (nxagentDefaultVisualIndex == UNDEFINED) + { + FatalError("Unable to find desired default visual.\n"); + } + } + else + { + vi.visualid = XVisualIDFromVisual(DefaultVisual(nxagentDisplay, + DefaultScreen(nxagentDisplay))); + nxagentDefaultVisualIndex = 0; + + for (i = 0; i < nxagentNumVisuals; i++) + { + if (vi.visualid == nxagentVisuals[i].visualid) + { + nxagentDefaultVisualIndex = i; + } + } + } +} + +void nxagentInitVisuals(void) +{ + XVisualInfo vi; + XVisualInfo *viList = NULL; + + long mask; + int i, viNumList; + + mask = VisualScreenMask; + vi.screen = DefaultScreen(nxagentDisplay); + vi.depth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)); + viList = XGetVisualInfo(nxagentDisplay, mask, &vi, &viNumList); + nxagentVisuals = (XVisualInfo *) malloc(viNumList * sizeof(XVisualInfo)); + nxagentNumVisuals = 0; + + for (i = 0; i < viNumList; i++) + { + if (viList[i].depth == vi.depth) + { + if (nxagentVisuals != NULL) + { + memcpy(nxagentVisuals + nxagentNumVisuals, viList + i, sizeof(XVisualInfo)); + } + + #ifdef DEBUG + fprintf(stderr, "nxagentInitVisuals: Visual:\n"); + fprintf(stderr, "\tdepth = %d\n", nxagentVisuals[nxagentNumVisuals].depth); + fprintf(stderr, "\tclass = %d\n", nxagentVisuals[nxagentNumVisuals].class); + fprintf(stderr, "\tmask = (%lu,%lu,%lu)\n", + nxagentVisuals[nxagentNumVisuals].red_mask, + nxagentVisuals[nxagentNumVisuals].green_mask, + nxagentVisuals[nxagentNumVisuals].blue_mask); + fprintf(stderr, "\tcolormap size = %d\n", nxagentVisuals[nxagentNumVisuals].colormap_size); + fprintf(stderr, "\tbits_per_rgb = %d\n", nxagentVisuals[nxagentNumVisuals].bits_per_rgb); + #endif + + nxagentNumVisuals++; + } + } + + if (nxagentVisuals != NULL) + { + nxagentVisuals = (XVisualInfo *) realloc(nxagentVisuals, + nxagentNumVisuals * sizeof(XVisualInfo)); + } + + XFree(viList); + + if (nxagentNumVisuals == 0 || nxagentVisuals == NULL) + { + FatalError("Unable to find any visuals.\n"); + } + + nxagentSetDefaultVisual(); +} + +void nxagentInitDepths() +{ + #ifdef TEST + int i; + #endif + + nxagentDepths = XListDepths(nxagentDisplay, DefaultScreen(nxagentDisplay), + &nxagentNumDepths); + + if (nxagentDepths == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentInitDepths: PANIC! Failed to get available depths.\n"); + #endif + + FatalError("Failed to get available depths and pixmap formats."); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentInitDepths: Got [%d] available depths:\n", + nxagentNumDepths); + + for (i = 0; i < nxagentNumDepths; i++) + { + fprintf(stderr, " [%d]", nxagentDepths[i]); + } + + fprintf(stderr, ".\n"); + } + #endif +} + +void nxagentInitPixmapFormats() +{ + int i, j; + int depth; + + /* + * Formats are created with no care of which are supported + * on the real display. Creating only formats supported + * by the remote end makes troublesome handling migration + * of session from a display to another. + */ + + nxagentNumPixmapFormats = 0; + + nxagentPixmapFormats = xalloc(nxagentNumDepths * sizeof(XPixmapFormatValues)); + + for (i = 1; i <= MAXDEPTH; i++) + { + depth = 0; + + for (j = 0; j < nxagentNumDepths; j++) + { + if (nxagentDepths[j] == i) + { + depth = i; + + break; + } + } + + if (depth != 0) + { + if (nxagentNumPixmapFormats >= MAXFORMATS) + { + FatalError("nxagentInitPixmapFormats: MAXFORMATS is too small for this server.\n"); + } + + nxagentPixmapFormats[nxagentNumPixmapFormats].depth = depth; + nxagentPixmapFormats[nxagentNumPixmapFormats].bits_per_pixel = nxagentBitsPerPixel(depth); + nxagentPixmapFormats[nxagentNumPixmapFormats].scanline_pad = BITMAP_SCANLINE_PAD; + + #ifdef TEST + fprintf(stderr, "nxagentInitPixmapFormats: Set format [%d] to depth [%d] " + "bits per pixel [%d] scanline pad [%d].\n", nxagentNumPixmapFormats, + depth, nxagentPixmapFormats[nxagentNumPixmapFormats].bits_per_pixel, + BITMAP_SCANLINE_PAD); + #endif + + nxagentNumPixmapFormats++; + } + } + + nxagentRemotePixmapFormats = XListPixmapFormats(nxagentDisplay, &nxagentRemoteNumPixmapFormats); + + if (nxagentRemotePixmapFormats == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentInitPixmapFormats: WARNING! Failed to get available remote pixmap formats.\n"); + #endif + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentInitPixmapFormats: Got [%d] available remote pixmap formats:\n", + nxagentRemoteNumPixmapFormats); + + for (i = 0; i < nxagentRemoteNumPixmapFormats; i++) + { + fprintf(stderr, "nxagentInitPixmapFormats: Remote pixmap format [%d]: depth [%d] " + "bits_per_pixel [%d] scanline_pad [%d].\n", i, nxagentRemotePixmapFormats[i].depth, + nxagentRemotePixmapFormats[i].bits_per_pixel, nxagentRemotePixmapFormats[i].scanline_pad); + } + } + #endif + + nxagentCheckForPixmapFormatsCompatibility(); +} + +void nxagentSetDefaultDrawables() +{ + int i, j; + + for (i = 0; i <= MAXDEPTH; i++) + { + nxagentDefaultDrawables[i] = None; + } + + for (i = 0; i < nxagentNumPixmapFormats; i++) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDefaultDrawables: Checking remote pixmap format [%d] with depth [%d] " + "bits per pixel [%d] scanline pad [%d].\n", i, nxagentPixmapFormats[i].depth, + nxagentPixmapFormats[i].bits_per_pixel, nxagentPixmapFormats[i].scanline_pad); + #endif + + if (nxagentPixmapFormats[i].depth == 24) + { + if (nxagentPixmapFormats[i].bits_per_pixel == 24) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDefaultDrawables: WARNING! Assuming remote pixmap " + "format [%d] as true 24 bits.\n", i); + #endif + + nxagentTrue24 = True; + } + } + + for (j = 0; j < nxagentNumDepths; j++) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDefaultDrawables: Checking depth at index [%d] with pixmap depth [%d] " + "and display depth [%d].\n", j, nxagentPixmapFormats[i].depth, nxagentDepths[j]); + #endif + + if ((nxagentPixmapFormats[i].depth == 1 || + nxagentPixmapFormats[i].depth == nxagentDepths[j]) && + nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] == None) + { + nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] = + XCreatePixmap(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + 1, 1, nxagentPixmapFormats[i].depth); + + #ifdef TEST + fprintf(stderr, "nxagentSetDefaultDrawables: Created default drawable [%lu] for depth [%d].\n", + nxagentDefaultDrawables[nxagentPixmapFormats[i].depth], nxagentPixmapFormats[i].depth); + #endif + } + } + + if (nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] == None) + { + #ifdef TEST + fprintf(stderr, "nxagentSetDefaultDrawables: WARNING! Forcing default drawable for depth [%d].\n", + nxagentPixmapFormats[i].depth); + #endif + + nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] = + XCreatePixmap(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + 1, 1, nxagentPixmapFormats[i].depth); + + #ifdef TEST + fprintf(stderr, "nxagentSetDefaultDrawables: Created default drawable [%lu] for depth [%d].\n", + nxagentDefaultDrawables[nxagentPixmapFormats[i].depth], nxagentPixmapFormats[i].depth); + #endif + } + } +} + +void nxagentCloseDisplay() +{ + #ifdef TEST + fprintf(stderr, "nxagentCloseDisplay: Called with full generation [%d] and display [%p].\n", + nxagentDoFullGeneration, (void *) nxagentDisplay); + #endif + + if (nxagentDoFullGeneration == 0 || + nxagentDisplay == NULL) + { + return; + } + + /* + * If nxagentDoFullGeneration is true, all + * the X resources will be destroyed upon + * closing the display connection, so there + * is no real need to generate additional + * traffic + */ + + xfree(nxagentDefaultColormaps); + nxagentDefaultColormaps = NULL; + + XFree(nxagentVisuals); + nxagentVisuals = NULL; + + xfree(nxagentDepths); + nxagentDepths = NULL; + + XFree(nxagentPixmapFormats); + nxagentPixmapFormats = NULL; + + XFree(nxagentRemotePixmapFormats); + nxagentRemotePixmapFormats = NULL; + + nxagentFreeFontCache(); +/* +FIXME: Is this needed? + + nxagentFreeFontMatchStuff(); +*/ + + /* + * Free the image cache. This is useful + * for detecting memory leaks. + */ + + if (nxagentDisplay != NULL) + { + NXFreeCache(nxagentDisplay); + + NXResetDisplay(nxagentDisplay); + } + + /* + * Kill all the running dialogs. + */ + + nxagentTerminateDialogs(); + + #ifdef TEST + fprintf(stderr, "nxagentCloseDisplay: Setting the display to NULL.\n"); + #endif + + XCloseDisplay(nxagentDisplay); + + nxagentDisplay = NULL; +} + +Bool nxagentMakeIcon(Display *display, Pixmap *nxIcon, Pixmap *nxMask) +{ + char *env_path = getenv("PATH"); + int lenght_env_path = 0; + char icon_filename [256]; + char default_path [256]; + char *icon_path = malloc( strlen(env_path) + sizeof(icon_filename) ); + FILE *icon_fp; + int status; + Bool success = False; + XlibPixmap IconPixmap; + XlibPixmap IconShape; + + if (env_path == NULL) + lenght_env_path = 0; + else + lenght_env_path = strlen(env_path) + 1; + strncpy(icon_filename, "", 255); + strncpy(default_path, "", 255); + + strcat(icon_filename, NXAGENT_ICON_NAME); + strcat(default_path,"/usr/NX/share/images/"); + strcat(default_path,icon_filename); + + if ((icon_fp = fopen(default_path, "r")) == NULL) + { + char *s; + char *temp_path = malloc(lenght_env_path + strlen(icon_filename) ); + char *temp_path1 = malloc(lenght_env_path + strlen(icon_filename) ); + + strncpy(temp_path, env_path, strlen(env_path)); + strncpy(temp_path1, "", lenght_env_path + strlen(icon_filename) ); + + while (strlen(temp_path) > 0) + { + s = strpbrk (temp_path, ":"); + if (s == NULL) break; + + strncpy (temp_path1, temp_path , strlen(temp_path) - strlen(s) ); + strncat (temp_path1, "/", 1); + strncat (temp_path1, icon_filename, strlen(icon_filename)); + if ((icon_fp = fopen(temp_path1, "r")) != NULL) + { + fclose (icon_fp); + success = True; + strcpy(icon_path,temp_path1); + break; + } + strncpy(temp_path1, "", lenght_env_path + strlen(icon_filename) ); + strncpy(temp_path1, s + 1, strlen(s)-1); + strncpy(temp_path, "", lenght_env_path + strlen(icon_filename) ); + strcpy(temp_path, temp_path1 ); + strncpy(temp_path1, "", lenght_env_path + strlen(icon_filename) ); + } + free(temp_path); + free(temp_path1); + } + else + { + fclose (icon_fp); + success = True; + strcpy(icon_path, default_path); + } + + if (success) + { + status = XpmReadFileToPixmap(display, + DefaultRootWindow(display), + icon_path, + &IconPixmap, + &IconShape, + NULL); + + if (status != XpmSuccess) + { + #ifdef TEST + fprintf(stderr, "nxagentMakeIcon: Xpm operation failed with error '%s'.\n", + XpmGetErrorString(status)); + #endif + + success = False; + } + } + + if (!success) + { + status = XpmCreatePixmapFromData(display, + DefaultRootWindow(display), + nxagentIconData, + &IconPixmap, + &IconShape, + NULL); + + if (status != XpmSuccess) + { + #ifdef TEST + fprintf(stderr, "nxagentMakeIcon: Xpm operation failed with error '%s'.\n", + XpmGetErrorString(status)); + #endif + + success = False; + } + else + { + success = True; + } + } + + free(icon_path); + + *nxIcon = IconPixmap; + *nxMask = IconShape; + + return success; +} + +Bool nxagentXServerGeometryChanged() +{ + return (WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) != + WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplayBackup))) || + (HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) != + HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplayBackup))); +} + +void nxagentBackupDisplayInfo(void) +{ + if (nxagentDisplayInfoSaved) + { + return; + } + + /* + * Since we need the display structure + * in order to behave correctly when no X + * connection is available, we must always + * have a good display record. + * It can be discarded only when a new X + * connection is available, so we store it + * in order to destroy whenever the recon- + * nection succed. + */ + + nxagentDisplayBackup = nxagentDisplay; + nxagentBitmapGCBackup = nxagentBitmapGC; + nxagentDepthsRecBackup = nxagentDepths; + nxagentNumDepthsRecBackup = nxagentNumDepths; + nxagentNumDefaultColormapsRecBackup = nxagentNumDefaultColormaps; + nxagentVisualsRecBackup = nxagentVisuals; + nxagentNumVisualsRecBackup = nxagentNumVisuals; + if (nxagentVisualHasBeenIgnored) + { + xfree(nxagentVisualHasBeenIgnored); + nxagentVisualHasBeenIgnored = NULL; + } + nxagentVisualHasBeenIgnored = xalloc(nxagentNumVisuals * sizeof(Bool)); + nxagentDefaultDepthRecBackup = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)); + nxagentDisplayWidthRecBackup = DisplayWidth(nxagentDisplay, DefaultScreen(nxagentDisplay)); + nxagentDisplayHeightRecBackup = DisplayHeight(nxagentDisplay, DefaultScreen(nxagentDisplay)); + nxagentRenderEnableRecBackup = nxagentRenderEnable; + + nxagentDisplayInfoSaved = True; +} + +void nxagentCleanupBackupDisplayInfo(void) +{ + xfree(nxagentDepthsRecBackup); + nxagentNumDepthsRecBackup = 0; + + nxagentNumDefaultColormapsRecBackup = 0; + + xfree(nxagentVisualsRecBackup); + nxagentNumVisualsRecBackup = 0; + + if (nxagentVisualHasBeenIgnored) + { + xfree(nxagentVisualHasBeenIgnored); + nxagentVisualHasBeenIgnored = NULL; + } + + nxagentDefaultDepthRecBackup = 0; + nxagentDisplayWidthRecBackup = 0; + nxagentDisplayHeightRecBackup = 0; + + if (nxagentDisplayBackup) + { + XCloseDisplay(nxagentDisplayBackup); + + nxagentDisplayBackup = NULL; + } + + if (nxagentBitmapGCBackup) + { + if (nxagentDisplayBackup) + { + XFreeGC(nxagentDisplayBackup, nxagentBitmapGCBackup); + } + else + { + xfree(nxagentBitmapGCBackup); + } + + nxagentBitmapGCBackup = NULL; + } + + nxagentDisplayInfoSaved = False; +} + +void nxagentDisconnectDisplay(void) +{ + switch (reconnectDisplayState) + { + case EVERYTHING_DONE: + if (nxagentBitmapGC && + nxagentBitmapGCBackup && + (nxagentBitmapGC != nxagentBitmapGCBackup)) + { + XFreeGC(nxagentDisplay, nxagentBitmapGC); + } + + nxagentBitmapGC = nxagentBitmapGCBackup; + case GOT_PIXMAP_FORMAT_LIST: + case GOT_DEPTH_LIST: + case ALLOC_DEF_COLORMAP: + if (nxagentDefaultColormaps) + { + int i; + + for (i = 0; i < nxagentNumDefaultColormaps; i++) + { + nxagentDefaultColormaps[i] = None; + } + } + case GOT_VISUAL_INFO: + case OPENED: + /* + * Actually we need the nxagentDisplay + * structure in order to let the agent + * go when no X connection is available. + */ + + if (nxagentDisplay && + nxagentDisplayBackup && + (nxagentDisplay != nxagentDisplayBackup)) + { + XCloseDisplay(nxagentDisplay); + } + case NOTHING: + nxagentDisplay = nxagentDisplayBackup; + break; + default: + FatalError("Display is in unknown state. Can't continue."); + } + + reconnectDisplayState = NOTHING; +} + +static int nxagentCheckForDefaultDepthCompatibility() +{ + int dDepth; + + dDepth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)); + + if (nxagentDefaultDepthRecBackup == dDepth) + { + #ifdef TEST + fprintf(stderr, "nxagentCheckForDefaultDepthCompatibility: New default depth [%d] " + "matches with old default depth.\n", dDepth); + #endif + + return 1; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckForDefaultDepthCompatibility: WARNING! New default depth [%d] " + "doesn't match with old default depth [%d].\n", dDepth, nxagentDefaultDepthRecBackup); + #endif + + return 0; + } +} + +static int nxagentCheckForDepthsCompatibility(int flexibility) +{ + int i, j; + int matched; + int compatible; + + if (nxagentNumDepths != nxagentNumDepthsRecBackup) + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! Number of new available depths [%d] " + "doesn't match with old depths [%d].\n", nxagentNumDepths, + nxagentNumDepthsRecBackup); + #endif + + return 0; + } + + compatible = 1; + + for (i = 0; i < nxagentNumDepths; i++) + { + matched = 0; + + for (j = 0; j < nxagentNumDepthsRecBackup; j++) + { + if (nxagentDepths[i] == nxagentDepthsRecBackup[j]) + { + matched = 1; + + break; + } + } + + if (matched == 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! Failed to match available depth [%d].\n", + nxagentDepths[i]); + #endif + + compatible = 0; + + break; + } + } + + + if (compatible == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentCheckForDepthsCompatibility: Internal depths match with " + "remote depths.\n"); + #endif + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! New available depths don't match with " + "old depths.\n"); + #endif + } + + return compatible; +} + +static int nxagentCheckForPixmapFormatsCompatibility() +{ + int i, j; + int matched; + int compatible; + + compatible = 1; + + if (nxagentNumPixmapFormats != nxagentRemoteNumPixmapFormats) + { + #ifdef DEBUG + fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: WARNING! Number of internal pixmap formats [%d] " + "doesn't match with remote formats [%d].\n", nxagentNumPixmapFormats, + nxagentRemoteNumPixmapFormats); + #endif + } + + for (i = 0; i < nxagentNumPixmapFormats; i++) + { + matched = 0; + + for (j = 0; j < nxagentRemoteNumPixmapFormats; j++) + { + if (nxagentPixmapFormats[i].depth == nxagentRemotePixmapFormats[j].depth && + nxagentPixmapFormats[i].bits_per_pixel == nxagentRemotePixmapFormats[j].bits_per_pixel && + nxagentPixmapFormats[i].scanline_pad == nxagentRemotePixmapFormats[j].scanline_pad) + { + matched = 1; + + break; + } + } + + if (matched == 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: WARNING! Failed to match internal " + "pixmap format depth [%d] bpp [%d] pad [%d].\n", nxagentPixmapFormats[i].depth, + nxagentPixmapFormats[i].bits_per_pixel, nxagentPixmapFormats[i].scanline_pad); + #endif + + compatible = 0; + } + } + + #ifdef TEST + + if (compatible == 1) + { + fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: Internal pixmap formats match with " + "remote pixmap formats.\n"); + } + + #endif + + return compatible; +} + +static int nxagentInitAndCheckVisuals(int flexibility) +{ + XVisualInfo viTemplate; + XVisualInfo *viList; + XVisualInfo *newVisuals; + + long viMask; + int i, n; + int matched; + int compatible; + int viNumList; + + compatible = 1; + + viMask = VisualScreenMask; + viTemplate.screen = DefaultScreen(nxagentDisplay); + viTemplate.depth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)); + viList = XGetVisualInfo(nxagentDisplay, viMask, &viTemplate, &viNumList); + + newVisuals = malloc(sizeof(XVisualInfo) * nxagentNumVisuals); + + for (i = 0; i < nxagentNumVisuals; i++) + { + matched = 0; + + for (n = 0; n < viNumList; n++) + { + if (nxagentCompareVisuals(nxagentVisuals[i], viList[n]) == 1) + { +/* +FIXME: Should the visual be ignored in this case? + We can flag the visuals with inverted masks, + and use this information to switch the masks + when contacting the remote X server. +*/ + if (nxagentVisuals[i].red_mask == viList[n].blue_mask && + nxagentVisuals[i].blue_mask == viList[n].red_mask) + { + #ifdef WARNING + fprintf(stderr, "nxagentInitAndCheckVisuals: WARNING! Red and blue mask inverted. " + "Forcing matching.\n"); + #endif + } + + matched = 1; + + nxagentVisualHasBeenIgnored[i] = FALSE; + + memcpy(newVisuals + i, viList + n, sizeof(XVisualInfo)); + + break; + } + } + + if (matched == 0) + { + if (nxagentVisuals[i].class == DirectColor) + { + #ifdef WARNING + fprintf(stderr, "nxagentInitAndCheckVisuals: WARNING! Ignoring not matched DirectColor visual.\n"); + #endif + + nxagentVisualHasBeenIgnored[i] = TRUE; + + memcpy(newVisuals + i, nxagentVisuals + i, sizeof(XVisualInfo)); + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentInitAndCheckVisuals: WARNING! Failed to match this visual:\n"); + fprintf(stderr, "\tdepth = %d\n", nxagentVisuals[i].depth); + fprintf(stderr, "\tclass = %d\n", nxagentVisuals[i].class); + fprintf(stderr, "\tmask = (%ld,%ld,%ld)\n", + nxagentVisuals[i].red_mask, + nxagentVisuals[i].green_mask, + nxagentVisuals[i].blue_mask); + fprintf(stderr, "\tcolormap size = %d\n", nxagentVisuals[i].colormap_size); + fprintf(stderr, "\tbits_per_rgb = %d\n", nxagentVisuals[i].bits_per_rgb); + #endif + + compatible = 0; + + break; + } + } + } + + XFree(viList); + + if (compatible == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentInitAndCheckVisuals: New visuals match with old visuals.\n"); + #endif + + nxagentVisuals = newVisuals; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentInitAndCheckVisuals: New visuals don't match with old visuals.\n"); + #endif + + free(newVisuals); + } + + return compatible; +} + +static int nxagentCheckForColormapsCompatibility(int flexibility) +{ + if (nxagentNumDefaultColormaps == nxagentNumDefaultColormapsRecBackup) + { + #ifdef TEST + fprintf(stderr, "nxagentCheckForColormapsCompatibility: Number of new colormaps [%d] " + "matches with old colormaps.\n", nxagentNumDefaultColormaps); + #endif + + return 1; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckForColormapsCompatibility: WARNING! Number of new colormaps [%d] " + "doesn't match with old colormaps [%d].\n", nxagentNumDefaultColormaps, + nxagentNumDefaultColormapsRecBackup); + #endif + + return 0; + } +} + +Bool nxagentReconnectDisplay(void *p0) +{ + int i; + int flexibility = *(int*)p0; + int packMethod, packQuality; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_DISPLAY_DEBUG) + fprintf(stderr, "nxagentReconnectDisplay\n"); + #endif + + if (reconnectDisplayState) + { + fprintf(stderr, "nxagentReconnectDisplay: Trying to reconnect a session " + "uncleanly disconnected\n"); + + return False; + } + + /* + * Reset the values to their defaults. + */ + + packMethod = nxagentPackMethod; + packQuality = nxagentPackQuality; + + nxagentPackMethod = -1; + nxagentPackQuality = -1; + nxagentSplitThreshold = -1; + + nxagentInstallSignalHandlers(); + + nxagentInstallDisplayHandlers(); + + nxagentDisplay = nxagentInternalOpenDisplay(nxagentDisplayName); + + nxagentPostInstallSignalHandlers(); + + nxagentPostInstallDisplayHandlers(); + + if (nxagentDisplay == NULL) + { + nxagentSetReconnectError(FAILED_RESUME_DISPLAY_ALERT, + "Couldn't open the display."); + + return FALSE; + } + + nxagentAddXConnection(); + + /* + * Display is now open. + */ + + reconnectDisplayState = OPENED; + + #ifdef NXAGENT_TIMESTAMP + + fprintf(stderr, "Display: Open of the display finished with time [%d] ms.\n", + GetTimeInMillis() - startTime); + + #endif + + if (nxagentCheckForDefaultDepthCompatibility() == 0) + { + nxagentSetReconnectError(FAILED_RESUME_DISPLAY_ALERT, + "Default display depth doesn't match."); + + return FALSE; + } + + nxagentUseNXTrans = nxagentPostProcessArgs(nxagentDisplayName, nxagentDisplay, + DefaultScreenOfDisplay(nxagentDisplay)); + + /* + * After processing the arguments all the + * timeout values have been set. Now we + * have to change the screen-saver timeout. + */ + + nxagentSetScreenSaverTime(); + + /* + * Init and compare the visuals. + */ + + if (nxagentInitAndCheckVisuals(flexibility) == FALSE) + { + nxagentSetReconnectError(FAILED_RESUME_VISUALS_ALERT, + "Couldn't restore the required visuals."); + + return FALSE; + } + + reconnectDisplayState = GOT_VISUAL_INFO; + + nxagentSetDefaultVisual(); + + nxagentInitAlphaVisual(); + + /* + * Re-allocate the colormaps. + */ + + nxagentNumDefaultColormaps = nxagentNumVisuals; + + nxagentDefaultColormaps = (Colormap *) xrealloc(nxagentDefaultColormaps, + nxagentNumDefaultColormaps * sizeof(Colormap)); + + if (nxagentDefaultColormaps == NULL) + { + FatalError("Can't allocate memory for the default colormaps\n"); + } + + reconnectDisplayState = ALLOC_DEF_COLORMAP; + + for (i = 0; i < nxagentNumDefaultColormaps; i++) + { + if (nxagentVisualHasBeenIgnored[i]) + { + nxagentDefaultColormaps[i] = (XID)0; + } + else + { + nxagentDefaultColormaps[i] = XCreateColormap(nxagentDisplay, + DefaultRootWindow(nxagentDisplay), + nxagentVisuals[i].visual, + AllocNone); + } + } + + nxagentCheckForColormapsCompatibility(flexibility); + + /* + * Check the display depth. + */ + + nxagentInitDepths(); + + reconnectDisplayState = GOT_DEPTH_LIST; + + if (nxagentCheckForDepthsCompatibility(flexibility) == 0) + { + nxagentSetReconnectError(FAILED_RESUME_DEPTHS_ALERT, + "Couldn't restore all the required depths."); + + return False; + } + + /* + * Check if all the required pixmap + * formats are supported. + */ + + nxagentInitPixmapFormats(); + + reconnectDisplayState = GOT_PIXMAP_FORMAT_LIST; + + /* + * Create a pixmap for each depth matching the + * local supported formats with format available + * on the remote display. + */ + + nxagentSetDefaultDrawables(); + + #ifdef RENDER + + if (nxagentRenderEnable) + { + nxagentRenderExtensionInit(); + } + + if (nxagentRenderEnableRecBackup != nxagentRenderEnable) + { + nxagentRenderEnable = nxagentRenderEnableRecBackup; + + nxagentSetReconnectError(FAILED_RESUME_RENDER_ALERT, + "Render extension not available or incompatible version."); + + return False; + } + + #endif + + nxagentBlackPixel = BlackPixel(nxagentDisplay, DefaultScreen(nxagentDisplay)); + nxagentWhitePixel = WhitePixel(nxagentDisplay, DefaultScreen(nxagentDisplay)); + + /* + * Initialize the agent's event mask that will be requested + * for the root or all the top level windows. If the nested + * window is a child of an existing window we will need to + * receive StructureNotify events. If we are going to manage + * the changes in root window's visibility we'll also need + * VisibilityChange events. + */ + + nxagentInitDefaultEventMask(); + + nxagentBitmapGC = XCreateGC(nxagentDisplay, nxagentDefaultDrawables[1], 0L, NULL); + + #ifdef TEST + fprintf(stderr, "nxagentReconnectDisplay: Going to create agent's confine window.\n"); + #endif + + nxagentConfineWindow = XCreateWindow(nxagentDisplay, + DefaultRootWindow(nxagentDisplay), + 0, 0, 1, 1, 0, 0, + InputOnly, + CopyFromParent, + 0L, NULL); + + #ifdef TEST + fprintf(stderr, "nxagentReconnectDisplay: Created agent's confine window with id [%ld].\n", + nxagentConfineWindow); + #endif + + nxagentLogoDepth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)); + + pV = nxagentVisuals[nxagentDefaultVisualIndex]; + + r = pV.red_mask; + g = pV.green_mask; + b = pV.blue_mask; + + if (!pV.red_mask || !pV.green_mask || !pV.blue_mask) + { + nxagentLogoBlack = 0x000000; + nxagentLogoRed = 0xff0000; + nxagentLogoWhite = 0xffffff; + } + else + { + for (or=0, off=0x800000; (r&(off>>or)) == 0; or++); + for (og=0, off=0x800000; (g&(off>>og)) == 0; og++); + for (ob=0, off=0x800000; (b&(off>>ob)) == 0; ob++); + + nxagentLogoRed = nxagentLogoColor(0xff0000); + nxagentLogoBlack = nxagentLogoColor(0x000000); + nxagentLogoWhite = 0xffffff; + } + + useXpmIcon = nxagentMakeIcon(nxagentDisplay, &nxagentIconPixmap, &nxagentIconShape); + + /* + * All went fine. We can continue + * handling our clients. + */ + + reconnectDisplayState = EVERYTHING_DONE; + + return True; +} + +void nxagentAddXConnection() +{ + int fd = XConnectionNumber(nxagentDisplay); + + nxagentXConnectionNumber = fd; + + #ifdef TEST + fprintf(stderr, "nxagentAddXConnection: Adding the X connection [%d] " + "to the device set.\n", nxagentXConnectionNumber); + #endif + + AddEnabledDevice(nxagentXConnectionNumber); +} + +void nxagentRemoveXConnection() +{ + #ifdef TEST + fprintf(stderr, "nxagentRemoveXConnection: Removing the X connection [%d] " + "from the device set.\n", nxagentXConnectionNumber); + #endif + + RemoveEnabledDevice(nxagentXConnectionNumber); +} + +/* + * Force an I/O error and wait until the NX trans- + * port is gone. It must be called before suspend- + * ing or terminating a session to ensure that the + * NX transport is terminated first. + */ + +void nxagentWaitDisplay() +{ + /* + * Disable the smart scheduler's interrupts. + */ + + #ifdef SMART_SCHEDULE + + #ifdef DEBUG + fprintf(stderr, "nxagentWaitDisplay: Stopping the smart schedule timer.\n"); + #endif + + nxagentStopTimer(); + + #endif + + if (nxagentDisplay != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentWaitDisplay: Going to shutdown the X connection [%d].\n", + nxagentXConnectionNumber); + #endif + + NXForceDisplayError(nxagentDisplay); + + XSync(nxagentDisplay, 0); + } + + #ifdef TEST + fprintf(stderr, "nxagentWaitDisplay: Going to wait for the NX transport.\n"); + #endif + + NXTransDestroy(NX_FD_ANY); + + #ifdef TEST + fprintf(stderr, "nxagentWaitDisplay: The NX transport is not running.\n"); + #endif + + /* + * Be sure the signal handlers are + * in a known state. + */ + + nxagentResetSignalHandlers(); +} + +/* + * This has not to do with the remote display but + * with the X server that the agent is impersonating. + * We have it here to be consistent with the other + * cleanup procedures which have mainly to do with + * the Xlib display connection. + */ + +void nxagentAbortDisplay() +{ + /* + * Be sure the X server socket in .X11-unix is + * deleted otherwise other users may to become + * unable to run a session on the same display. + */ + + #ifdef TEST + fprintf(stderr, "nxagentAbortDisplay: Cleaning up the X server sockets.\n"); + #endif + + CloseWellKnownConnections(); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Display.h b/nx-X11/programs/Xserver/hw/nxagent/Display.h new file mode 100644 index 000000000..d18785b60 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Display.h @@ -0,0 +1,179 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Display_H__ +#define __Display_H__ + +#define MAXDEPTH 32 +#define MAXVISUALSPERDEPTH 256 + +extern Display *nxagentDisplay; +extern Display *nxagentShadowDisplay; +extern XVisualInfo *nxagentVisuals; +extern int nxagentNumVisuals; +extern int nxagentDefaultVisualIndex; +extern Colormap *nxagentDefaultColormaps; +extern int nxagentNumDefaultColormaps; +extern int *nxagentDepths; +extern int nxagentNumDepths; +extern XPixmapFormatValues *nxagentPixmapFormats; +extern int nxagentNumPixmapFormats; +extern Pixel nxagentBlackPixel; +extern Pixel nxagentWhitePixel; +extern Drawable nxagentDefaultDrawables[MAXDEPTH + 1]; +extern Pixmap nxagentScreenSaverPixmap; + +/* + * The "confine" window is used in nxagentConstrainCursor(). + * We are currently overriding the original Xnest behaviour + * and just skip the "constrain" stuff. + */ + +extern Window nxagentConfineWindow; + +/* + * Keyboard and pointer are handled as they were hardware + * devices, that is we translate the key codes according to + * our own transcripts. We inherit this behaviour from Xnest. + * The following mask will contain the event mask selected + * for the root window. All the keyboard and pointer events + * are enqueued to the mi that translates and posts them to + * managed clients. + */ + +extern unsigned long nxagentEventMask; + +void nxagentOpenDisplay(int argc, char *argv[]); +void nxagentWaitDisplay(void); +void nxagentCloseDisplay(void); +void nxagentAbortDisplay(void); + +void nxagentAddXConnection(void); +void nxagentRemoveXConnection(void); + +Bool nxagentXServerGeometryChanged(void); + +/* + * Create the default drawables. + */ + +void nxagentGetDepthsAndPixmapFormats(void); +void nxagentSetDefaultDrawables(void); + +extern Bool nxagentTrue24; + +void nxagentBackupDisplayInfo(void); +void nxagentCleanupBackupDisplayInfo(void); + +void nxagentInstallDisplayHandlers(void); +void nxagentPostInstallDisplayHandlers(void); +void nxagentResetDisplayHandlers(void); + +void nxagentInstallSignalHandlers(void); +void nxagentPostInstallSignalHandlers(void); +void nxagentResetSignalHandlers(void); + +void nxagentDisconnectDisplay(void); +Bool nxagentReconnectDisplay(void *p0); + +/* + * Deal with the smart scheduler. + */ + +#ifdef SMART_SCHEDULE + +#define nxagentInitTimer() \ +\ + SmartScheduleInit(); + +#define nxagentStopTimer() \ +\ + if (SmartScheduleTimerStopped == 0) \ + { \ + SmartScheduleStopTimer(); \ + } \ +\ + SmartScheduleIdle = 1; + +#define nxagentStartTimer() \ +\ + if (SmartScheduleTimerStopped == 1) \ + { \ + SmartScheduleStartTimer(); \ + } \ +\ + SmartScheduleIdle = 0; + +#define nxagentDisableTimer() \ +\ + if (SmartScheduleTimerStopped == 0) \ + { \ + SmartScheduleStopTimer(); \ + } \ +\ + SmartScheduleDisable = 1; + +#endif /* #ifdef SMART_SCHEDULE */ + +/* + * File descriptor currently used by + * Xlib for the agent display. + */ + +extern int nxagentXConnectionNumber; + +/* + * File descriptor currently used by + * Xlib for the agent shadow display. + */ + +extern int nxagentShadowXConnectionNumber; + +int nxagentServerOrder(void); + +#define nxagentClientOrder(client) \ + ((client)->swapped ? !nxagentServerOrder() : nxagentServerOrder()) + +/* + * Terminate the agent after the next + * dispatch loop. + */ + +#define nxagentTerminateSession() \ + do \ + { \ + dispatchException |= DE_TERMINATE; \ + \ + isItTimeToYield = TRUE; \ + } \ + while (0) + +#endif /* __Display_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Drawable.c b/nx-X11/programs/Xserver/hw/nxagent/Drawable.c new file mode 100644 index 000000000..89cc1a846 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Drawable.c @@ -0,0 +1,3201 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "dixstruct.h" +#include "../../fb/fb.h" + +#include "Agent.h" +#include "Display.h" +#include "Screen.h" +#include "Trap.h" +#include "Image.h" +#include "Drawable.h" +#include "Client.h" +#include "Visual.h" +#include "Events.h" +#include "GCs.h" +#include "Utils.h" +#include "Handlers.h" +#include "Pixels.h" +#include "Reconnect.h" + +#include "NXlib.h" + +#include "mibstorest.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +/* + * The list of rectangles composing a region + * s returned by nxagentGetOptimizedRegion- + * Boxes() instead of REGION_RECTS(). + */ + +#define USE_OPTIMIZED_BOXES + +/* + * The rectangles composing a region are de- + * fragmented to reduce the number of synch- + * ronizing PutImage's. + */ + +#define ADVANCED_BOXES_DEFRAG + +/* + * If defined, send the XClearArea at the end + * of the loop synchronizing the shadow pixmap. + * In this way, large images can be splitted but + * the user will see more updates togheter. + */ + +#undef COLLECTED_UPDATES + +#ifdef ADVANCED_BOXES_DEFRAG +#define INCLUDE_MARGIN 10 +#endif + +struct nxagentExposeBackground +{ + PixmapPtr pBackground; + RegionPtr pExpose; +}; + +RESTYPE RT_NX_CORR_BACKGROUND; +RESTYPE RT_NX_CORR_WINDOW; +RESTYPE RT_NX_CORR_PIXMAP; + +int nxagentCorruptedPixmaps = 0; +int nxagentCorruptedWindows = 0; +int nxagentCorruptedBackgrounds = 0; + +int nxagentForceSynchronization = 0; + +_nxagentSynchronizationRec nxagentSynchronization = { (DrawablePtr) NULL, 0, 0, 0, 0, 0 }; + +RegionPtr nxagentDeferredBackgroundExposures = NullRegion; + +/* + * Predicate functions used to synchronize the + * content of the remote drawable with the data + * stored in the virtual frame-buffer. + */ + +void nxagentSynchronizeDrawablePredicate(void *p0, XID x1, void *p2); +void nxagentExposeBackgroundPredicate(void *p0, XID x1, void *p2); + +/* + * Imported from NXresource.c + */ + +extern int nxagentFindClientResource(int, RESTYPE, pointer); + +unsigned long nxagentGetColor(DrawablePtr pDrawable, int xPixel, int yPixel); +unsigned long nxagentGetDrawableColor(DrawablePtr pDrawable); +unsigned long nxagentGetRegionColor(DrawablePtr pDrawable, RegionPtr pRegion); + +int nxagentSynchronizeDrawable(DrawablePtr pDrawable, int wait, unsigned int breakMask, WindowPtr owner) +{ + int result; + + pDrawable = nxagentSplitDrawable(pDrawable); + + if (nxagentLosslessTrap == 0) + { + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawable: Drawable [%s][%p] with id [%ld] already " + "synchronized.\n", nxagentDrawableType(pDrawable), + (void *) pDrawable, pDrawable -> id); + #endif + + return 0; + } + } + + /* + * What we want here is to avoid drawing on the + * framebuffer and just perform the operation + * on the real X server. This is the purpose of + * the FB trap. At the same time we also want + * to avoid a split, so that the image will be + * transferred in a single operation. + */ + + nxagentFBTrap = 1; + + nxagentSplitTrap = 1; + + result = nxagentSynchronizeDrawableData(pDrawable, breakMask, owner); + + nxagentSplitTrap = 0; + + nxagentFBTrap = 0; + + if (wait == DO_WAIT && nxagentSplitResource(pDrawable) != NULL) + { + nxagentWaitDrawable(pDrawable); + } + + #ifdef TEST + + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + fprintf(stderr, "nxagentSynchronizeDrawable: Drawable %s [%p] with id [%ld] now synchronized.\n", + nxagentDrawableType(pDrawable), (void *) pDrawable, pDrawable -> id); + } + else + { + fprintf(stderr, "nxagentSynchronizeDrawable: Drawable %s [%p] with id [%ld] not fully synchronized.\n", + nxagentDrawableType(pDrawable), (void *) pDrawable, pDrawable -> id); + } + + #endif + + return result; +} + +int nxagentSynchronizeDrawableData(DrawablePtr pDrawable, unsigned int breakMask, WindowPtr owner) +{ + int width, height, depth, length; + unsigned int leftPad, format; + + char *data = NULL; + DrawablePtr pSrcDrawable; + GCPtr pGC; + + int success; + + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + leftPad = 0; + + width = pDrawable -> width; + height = pDrawable -> height; + depth = pDrawable -> depth; + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawableData: Synchronizing drawable (%s) with geometry [%d][%d][%d].\n", + nxagentDrawableType(pDrawable), width, height, depth); + #endif + + format = (depth == 1) ? XYPixmap : ZPixmap; + + length = nxagentImageLength(width, height, format, leftPad, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentSynchronizeDrawableData: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + success = 0; + + goto nxagentSynchronizeDrawableDataEnd; + } + + pSrcDrawable = (pDrawable -> type == DRAWABLE_PIXMAP ? + ((DrawablePtr) nxagentVirtualPixmap((PixmapPtr) pDrawable)) : + pDrawable); + + /* + * Synchronize the whole pixmap if we need + * to download a fresh copy with lossless + * compression turned off. + */ + + if (nxagentLosslessTrap == 1) + { + pGC = nxagentGetGraphicContext(pDrawable); + + if (pGC == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentSynchronizeDrawableData: WARNING! Failed to get the temporary GC.\n"); + #endif + + success = 0; + + goto nxagentSynchronizeDrawableDataFree; + } + + ValidateGC(pDrawable, pGC); + + fbGetImage(pSrcDrawable, 0, 0, + width, height, format, AllPlanes, data); + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawableData: Forcing synchronization of " + "pixmap at [%p] with lossless compression.\n", (void *) pDrawable); + #endif + + nxagentPutImage(pDrawable, pGC, depth, 0, 0, + width, height, leftPad, format, data); + + success = 1; + + goto nxagentSynchronizeDrawableDataFree; + } + else if (nxagentReconnectTrap == 1) + { + /* + * The pixmap data is not synchronized unless + * we need it. We noticed we have to reconnect + * the pixmaps used by the GC's clip mask. + * The other data will be synchronized on demand. + */ + + if (pDrawable -> depth == 1) + { + #ifdef TEST + + if (nxagentReconnectTrap == 1) + { + static int totalLength; + static int totalReconnectedPixmaps; + + totalLength += length; + totalReconnectedPixmaps++; + + fprintf(stderr, "nxagentSynchronizeDrawableData: Reconnecting pixmap at [%p] [%dx%d] " + "Depth [%d] Size [%d]. Total size [%d]. Total reconnected pixmaps [%d].\n", + (void *) pDrawable, width, height, depth, length, + totalLength, totalReconnectedPixmaps); + } + + #endif + + pGC = nxagentGetGraphicContext(pDrawable); + + if (pGC == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentSynchronizeDrawableData: WARNING! Failed to create the temporary GC.\n"); + #endif + + success = 0; + + goto nxagentSynchronizeDrawableDataFree; + } + + ValidateGC(pDrawable, pGC); + + fbGetImage(pSrcDrawable, 0, 0, + width, height, format, AllPlanes, data); + + nxagentPutImage(pDrawable, pGC, depth, 0, 0, + width, height, leftPad, format, data); + + success = 1; + + goto nxagentSynchronizeDrawableDataFree; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawableData: Skipping synchronization of " + "pixmap at [%p][%p] during reconnection.\n", (void *) pDrawable, (void*) nxagentVirtualPixmap((PixmapPtr)pDrawable)); + #endif + + nxagentMarkCorruptedRegion(pDrawable, NullRegion); + + success = 1; + + goto nxagentSynchronizeDrawableDataFree; + } + } + } + + /* + * By calling this function with the NullRegion + * as parameter we are requesting to synchro- + * nize the full visible corrupted region of + * the drawable. + */ + + success = nxagentSynchronizeRegion(pDrawable, NullRegion, breakMask, owner); + +nxagentSynchronizeDrawableDataFree: + + if (data != NULL) + { + xfree(data); + } + +nxagentSynchronizeDrawableDataEnd: + + return success; +} + +/* + * If pRegion is NullRegion, all the viewable + * corrupted region will be synchronized. + */ + +int nxagentSynchronizeRegion(DrawablePtr pDrawable, RegionPtr pRegion, unsigned int breakMask, WindowPtr owner) +{ + GCPtr pGC; + DrawablePtr pSrcDrawable; + BoxPtr pBox; + RegionPtr clipRegion; + + RegionRec tileRegion; + RegionRec exposeRegion; + BoxRec box; + BoxRec tileBox; + + #ifdef COLLECTED_UPDATES + RegionRec collectedUpdates; + #endif + + char *data; + + int nBox; + int x, y; + int w, h; + int tileWidth, tileHeight; + int length, format, leftPad; + int i; + int saveTrap; + int success; + int useStoredBitmap; + + unsigned long now; + unsigned long elapsedTime; + + + leftPad = 0; + success = 0; + data = NULL; + pGC = NULL; + clipRegion = NullRegion; + + #ifdef COLLECTED_UPDATES + REGION_INIT(pDrawable -> pScreen, &collectedUpdates, NullBox, 1); + #endif + + REGION_INIT(pDrawable -> pScreen, &exposeRegion, NullBox, 1); + + if (nxagentDrawableBitmap(pDrawable) != NullPixmap && + nxagentDrawableStatus((DrawablePtr) nxagentDrawableBitmap(pDrawable)) == Synchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Drawable [%s] at [%p] has an already synchronized " + "bitmap at [%p].\n", nxagentDrawableType(pDrawable), + (void *) pDrawable, (void *) nxagentDrawableBitmap(pDrawable)); + #endif + + nxagentDestroyDrawableBitmap(pDrawable); + } + + /* + * The stored bitmap may be used if we + * are going to synchronize the full + * drawable. + */ + + useStoredBitmap = (nxagentDrawableBitmap(pDrawable) != NullPixmap && pRegion == NullRegion); + + if (useStoredBitmap != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Drawable [%s] at [%p] has a synchronization bitmap " + "[%d,%d,%d,%d] with [%ld] rects.\n", nxagentDrawableType(pDrawable), + (void *) pDrawable, nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x1, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y1, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x2, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y2, + REGION_NUM_RECTS(nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)))); + #endif + + clipRegion = nxagentCreateRegion(pDrawable, NULL, 0, 0, pDrawable -> width, pDrawable -> height); + + /* + * Intersecting the viewable region of the + * drawable with the region remaining from + * a previous loop. + */ + + REGION_INTERSECT(pDrawable -> pScreen, clipRegion, clipRegion, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable))); + + /* + * The bitmap regions used in the synchro- + * nizations are only those corrupted also + * on the drawable. In this way, if we put + * a tile in a bad position (e.g. if the + * corrupted region moves), the next synch- + * ronization will fix the error. + */ + + REGION_INTERSECT(pDrawable -> pScreen, clipRegion, clipRegion, + nxagentCorruptedRegion(pDrawable)); + + /* + * The bitmap to synchronize is clipped. + */ + + if (REGION_NIL(clipRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: The bitmap region [%d,%d,%d,%d] is not viewable. " + "Destroying it.\n", clipRegion -> extents.x1, clipRegion -> extents.y1, + clipRegion -> extents.x2, clipRegion -> extents.y2); + #endif + + nxagentDestroyDrawableBitmap(pDrawable); + + goto nxagentSynchronizeRegionFree; + } + + /* + * Using the saved bitmap as source, instead + * of the drawable itself. + */ + + pSrcDrawable = ((DrawablePtr) nxagentVirtualPixmap(nxagentDrawableBitmap(pDrawable))); + } + else + { + if (pRegion != NullRegion && REGION_NIL(pRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Region [%d,%d,%d,%d] is nil. Skipping synchronization.\n", + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2); + #endif + + goto nxagentSynchronizeRegionFree; + } + + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: The [%s] at [%p] is already synchronized.\n", + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + goto nxagentSynchronizeRegionFree; + } + + /* + * Creating a region containing the viewable + * area of drawable. + */ + + clipRegion = nxagentCreateRegion(pDrawable, NULL, 0, 0, pDrawable -> width, pDrawable -> height); + + /* + * If the corrupted region is not viewable, we + * can skip the synchronization. + */ + + REGION_INTERSECT(pDrawable -> pScreen, clipRegion, clipRegion, nxagentCorruptedRegion(pDrawable)); + + if (REGION_NIL(clipRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: The corrupted region [%d,%d,%d,%d] is not viewable " + "on [%s] at [%p]. Skipping the synchronization.\n", clipRegion -> extents.x1, + clipRegion -> extents.y1, clipRegion -> extents.x2, clipRegion -> extents.y2, + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + goto nxagentSynchronizeRegionFree; + } + + /* + * We can skip the synchronization if the re- + * quested region is not corrupted. Specifying + * a NullRegion as parameter, all the viewable + * corrupted region will be synchronized. + */ + + if (pRegion != NullRegion) + { + REGION_INTERSECT(pDrawable -> pScreen, clipRegion, clipRegion, pRegion); + + if (REGION_NIL(clipRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Region requested [%d,%d,%d,%d] already " + "synchronized on [%s] at [%p].\n", pRegion -> extents.x1, + pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2, + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + goto nxagentSynchronizeRegionFree; + } + } + + pSrcDrawable = (pDrawable -> type == DRAWABLE_PIXMAP ? + ((DrawablePtr) nxagentVirtualPixmap((PixmapPtr) pDrawable)) : + pDrawable); + } + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Synchronizing region with coordinates [%d,%d,%d,%d] " + "on [%s] at [%p].\n", clipRegion -> extents.x1, clipRegion -> extents.y1, + clipRegion -> extents.x2, clipRegion -> extents.y2, + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + saveTrap = nxagentGCTrap; + + nxagentGCTrap = 0; + + nxagentFBTrap = 1; + + nxagentSplitTrap = 1; + + pGC = nxagentGetGraphicContext(pDrawable); + + if (pGC == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Failed to create the temporary GC.\n"); + #endif + + goto nxagentSynchronizeRegionFree; + } + + ValidateGC(pDrawable, pGC); + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Going to synchronize [%ld] rects of [%s] at [%p].\n", + REGION_NUM_RECTS(clipRegion), (pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window"), + (void *) pDrawable); + + fprintf(stderr, "nxagentSynchronizeRegion: Extents geometry [%d,%d,%d,%d].\n", + clipRegion -> extents.x1, clipRegion -> extents.y1, clipRegion -> extents.x2, clipRegion -> extents.y2); + + fprintf(stderr, "nxagentSynchronizeRegion: Drawable geometry [%d,%d,%d,%d].\n", + pDrawable -> x, pDrawable -> y, pDrawable -> width, pDrawable -> height); + #endif + + w = tileWidth = (nxagentOption(TileWidth) > pDrawable -> width ? pDrawable -> width : nxagentOption(TileWidth)); + h = tileHeight = (nxagentOption(TileHeight) > pDrawable -> height ? pDrawable -> height : nxagentOption(TileHeight)); + + #ifdef DEBUG + fprintf(stderr, "nxagentSynchronizeRegion: Using tiles of size [%dx%d].\n", tileWidth, tileHeight); + #endif + + data = nxagentAllocateImageData(w, h, pDrawable -> depth, &length, &format); + + if (data == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Failed to allocate memory for synchronization.\n"); + #endif + + goto nxagentSynchronizeRegionFree; + } + + #ifndef USE_OPTIMIZED_BOXES + + pBox = REGION_RECTS(clipRegion); + + #else + + pBox = nxagentGetOptimizedRegionBoxes(clipRegion); + + #endif /* USE_OPTIMIZED_BOXES */ + + nBox = REGION_NUM_RECTS(clipRegion); + + now = GetTimeInMillis(); + + nxagentSynchronization.abort = 0; + + /* + * Going to split the updated region into small blocks. + */ + + for (i = 0; i < nBox; i++) + { + #ifdef USE_OPTIMIZED_BOXES + + if (pBox[i].x1 == 0 && pBox[i].y1 == 0 && + pBox[i].x2 == 0 && pBox[i].y2 == 0) + { + continue; + } + + #endif + + box = pBox[i]; + + for (y = box.y1; y < box.y2; y += h) + { + h = MIN(box.y2 - y, tileHeight); + + for (x = box.x1; x < box.x2; x += w) + { + w = MIN(box.x2 - x, tileWidth); + + if (canBreakOnTimeout(breakMask)) + { + /* + * Abort the synchronization loop if it + * lasts for more than DeferTimeout + * milliseconds. + */ + + elapsedTime = GetTimeInMillis() - now; + + if (elapsedTime > nxagentOption(DeferTimeout)) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with " + "[%lu] ms elapsed.\n", elapsedTime); + #endif + + nxagentSynchronization.abort = 1; + + goto nxagentSynchronizeRegionStop; + } + } + + /* + * Abort the loop if we go out of bandwidth. + */ + + if (breakOnCongestionDrawable(breakMask, pDrawable) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with " + "congestion [%d] blocking [%d].\n", nxagentCongestion, + nxagentBlocking); + #endif + + nxagentSynchronization.abort = 1; + + goto nxagentSynchronizeRegionStop; + } + + /* + * Abort the loop if the display blocks. + */ + + if (breakOnBlocking(breakMask) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with " + "blocking [%d] congestion [%d].\n", nxagentBlocking, + nxagentCongestion); + #endif + + nxagentSynchronization.abort = 1; + + goto nxagentSynchronizeRegionStop; + } + + tileBox.x1 = x; + tileBox.y1 = y; + tileBox.x2 = x + w; + tileBox.y2 = y + h; + + #ifdef DEBUG + fprintf(stderr, "nxagentSynchronizeRegion: Going to synchronize tile [%d,%d,%d,%d].\n", + tileBox.x1, tileBox.y1, tileBox.x2, tileBox.y2); + #endif + + nxagentGetImage(pSrcDrawable, x, y, w, h, format, AllPlanes, data); + + nxagentRealizeImage(pDrawable, pGC, pDrawable -> depth, + x, y, w, h, leftPad, format, data); + + /* + * Going to unmark the synchronized + * region. + */ + + REGION_INIT(pDrawable -> pScreen, &tileRegion, &tileBox, 1); + + REGION_UNION(pDrawable -> pScreen, &exposeRegion, &exposeRegion, &tileRegion); + + #ifdef COLLECTED_UPDATES + REGION_APPEND(pDrawable -> pScreen, &collectedUpdates, &tileRegion); + #endif + + if (useStoredBitmap != 0) + { + /* + * When a bitmap's tile is synchronized, + * we can clear the corresponding region. + * We can't use the nxagentUnmarkCorrupted- + * Region because we have not a resource + * associated to this pixmap. + */ + + REGION_SUBTRACT(pDrawable -> pScreen, nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)), + nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)), &tileRegion); + + /* + * The drawable's corrupted region can + * be cleared if the bitmap's tile data + * matches the drawable's content at the + * same position. + */ + + if (nxagentDrawableStatus(pDrawable) == NotSynchronized) + { + char *cmpData; + + int cmpLength, cmpFormat; + + cmpData = nxagentAllocateImageData(w, h, pDrawable -> depth, &cmpLength, &cmpFormat); + + if (cmpData != NULL) + { + nxagentGetImage(pDrawable, x, y, w, h, format, AllPlanes, cmpData); + + if (memcmp(data, cmpData, cmpLength) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Tile [%d,%d,%d,%d] matches drawable's data at same position.\n", + x, y, x + w, y + h); + #endif + + nxagentUnmarkCorruptedRegion(pDrawable, &tileRegion); + } + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Failed to allocate memory to compare tiles.\n"); + #endif + } + + if (cmpData != NULL) + { + xfree(cmpData); + } + } + } + else + { + nxagentUnmarkCorruptedRegion(pDrawable, &tileRegion); + + if (nxagentDrawableBitmap(pDrawable) != NullPixmap) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Going to clean bitmap at [%p] with newer data.\n", + (void *) nxagentDrawableBitmap(pDrawable)); + #endif + + REGION_SUBTRACT(pDrawable -> pScreen, nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)), + nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)), &tileRegion); + } + } + + REGION_UNINIT(pDrawable -> pScreen, &tileRegion); + + #if !defined(COLLECTED_UPDATES) + + if (owner != NULL) + { + if (nxagentOption(Shadow) == 1 && + (nxagentOption(XRatio) != DONT_SCALE || + nxagentOption(YRatio) != DONT_SCALE)) + { + int scaledx; + int scaledy; + int scaledw; + int scaledh; + + scaledx = nxagentScale(x, nxagentOption(XRatio)); + scaledy = nxagentScale(y, nxagentOption(YRatio)); + + scaledw = nxagentScale(x + w, nxagentOption(XRatio)) - scaledx; + scaledh = nxagentScale(y + h, nxagentOption(YRatio)) - scaledy; + + XClearArea(nxagentDisplay, nxagentWindow(owner), scaledx, scaledy, scaledw, scaledh, 0); + } + else + { + XClearArea(nxagentDisplay, nxagentWindow(owner), x, y, w, h, 0); + } + } + + #endif /* #if !defined(COLLECTED_UPDATES) */ + + /* + * Abort the loop on the user's input. + * This is done here to check for events + * read after the flush caused by the + * PutImage. + */ + + nxagentDispatchHandler((ClientPtr) 0, 0, 0); + + if (breakOnEvent(breakMask) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with " + "new input events.\n"); + #endif + + nxagentSynchronization.abort = 1; + + goto nxagentSynchronizeRegionStop; + } + } + } + } + +nxagentSynchronizeRegionStop: + + nxagentSplitTrap = 0; + + nxagentFBTrap = 0; + + nxagentGCTrap = saveTrap; + + success = 1; + + if (nxagentOption(Shadow) == 0) + { + if (nxagentSynchronization.abort == 1) + { + /* + * Storing the pointer to the drawable we + * were synchronizing when the loop aborted. + * It is used in nxagentSynchronizeDrawable- + * Predicate. + */ + + nxagentSynchronization.pDrawable = pDrawable; + nxagentSynchronization.drawableType = pDrawable -> type; + + if (nxagentDrawableBitmap(pDrawable) == NullPixmap) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Going to create the synchronization bitmap.\n"); + #endif + + nxagentCreateDrawableBitmap(pDrawable); + } + } + else + { + if (nxagentDrawableBitmap(pDrawable) != NullPixmap) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeRegion: Synchronization loop finished. Going to destroy synchronization bitmap.\n"); + #endif + + nxagentDestroyDrawableBitmap(pDrawable); + } + } + + if (pDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1 && + REGION_NIL(&exposeRegion) == 0) + { + struct nxagentExposeBackground eb; + + int i; + + eb.pBackground = (PixmapPtr) pDrawable; + eb.pExpose = &exposeRegion; + + for (i = 0; i < MAXCLIENTS; i++) + { + if (clients[i] != NULL) + { + FindClientResourcesByType(clients[i], RT_WINDOW, + nxagentExposeBackgroundPredicate, &eb); + } + } + } + } + #ifdef COLLECTED_UPDATES + else + { + if (owner != NULL) + { + int overlap = 0; + + REGION_VALIDATE(pDrawable -> pScreen, &collectedUpdates, &overlap); + + for (i = 0; i < REGION_NUM_RECTS(&collectedUpdates); i++) + { + x = REGION_RECTS(&collectedUpdates)[i].x1; + y = REGION_RECTS(&collectedUpdates)[i].y1; + w = REGION_RECTS(&collectedUpdates)[i].x2 - REGION_RECTS(&collectedUpdates)[i].x1; + h = REGION_RECTS(&collectedUpdates)[i].y2 - REGION_RECTS(&collectedUpdates)[i].y1; + + if (nxagentOption(Shadow) == 1 && + (nxagentOption(XRatio) != DONT_SCALE || + nxagentOption(YRatio) != DONT_SCALE)) + { + int scaledx; + int scaledy; + int scaledw; + int scaledh; + + scaledx = nxagentScale(x, nxagentOption(XRatio)); + scaledy = nxagentScale(y, nxagentOption(YRatio)); + + scaledw = nxagentScale(x + w, nxagentOption(XRatio)) - scaledx; + scaledh = nxagentScale(y + h, nxagentOption(YRatio)) - scaledy; + + XClearArea(nxagentDisplay, nxagentWindow(owner), scaledx, scaledy, scaledw, scaledh, 0); + } + else + { + XClearArea(nxagentDisplay, nxagentWindow(owner), x, y, w, h, 0); + } + } + } + } + #endif /* #ifdef COLLECTED_UPDATES */ + +nxagentSynchronizeRegionFree: + + if (clipRegion != NullRegion) + { + nxagentFreeRegion(pDrawable, clipRegion); + } + + if (data != NULL) + { + xfree(data); + } + + REGION_UNINIT(pDrawable -> pScreen, &exposeRegion); + + #ifdef COLLECTED_UPDATES + + REGION_UNINIT(pDrawable -> pScreen, &collectedUpdates); + + #endif /* #ifdef COLLECTED_UPDATES */ + + return success; +} + +void nxagentSynchronizeBox(DrawablePtr pDrawable, BoxPtr pBox, unsigned int breakMask) +{ + RegionPtr pRegion; + + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeBox: The [%s] at [%p] is already synchronized.\n", + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + return; + } + + if (pBox == NullBox) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeBox: Going to synchronize the whole [%s] at [%p].\n", + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + nxagentSynchronizeRegion(pDrawable, NullRegion, breakMask, NULL); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeBox: Going to create a region from box [%d,%d,%d,%d].\n", + pBox -> x1, pBox -> y1, pBox -> x2, pBox -> y2); + #endif + + pRegion = nxagentCreateRegion(pDrawable, NULL, pBox -> x1, pBox -> y1, + pBox -> x2 - pBox -> x1, pBox -> y2 - pBox -> y1); + + + if (REGION_NIL(pRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeBox: Resulting region [%d,%d,%d,%d] is nil. Skipping synchronization.\n", + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2); + #endif + + nxagentFreeRegion(pDrawable, pRegion); + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeBox: Going to synchronize the region [%d,%d,%d,%d] of " + "[%s] at [%p].\n", pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, + pRegion -> extents.y2, nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + nxagentSynchronizeRegion(pDrawable, pRegion, breakMask, NULL); + + nxagentFreeRegion(pDrawable, pRegion); + } +} + +void nxagentSynchronizeDrawablePredicate(void *p0, XID x1, void *p2) +{ + DrawablePtr pDrawable = (DrawablePtr) p0; + unsigned int *breakMask = (unsigned int *) p2; + + int shouldClearHiddenRegion = 1; + + /* + * The nxagentSynchronization.abort propa- + * gates a break condition across the resour- + * ces loop, in order to block also the sub- + * sequent synchronizations. + */ + + if (nxagentSynchronization.abort == 1 || + nxagentDrawableStatus(pDrawable) == Synchronized) + { + return; + } + + /* + * In order to implement a kind of round-robin + * synchronization, the previous incomplete + * drawable synchronization is saved to jump + * to the next resource available of same type. + */ + + if (nxagentSynchronization.pDrawable != NULL && + pDrawable -> type == nxagentSynchronization.drawableType) + { + if (nxagentSynchronization.pDrawable != pDrawable) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Skipping drawable [%s][%p] while looking " + "for last synchronized drawable [%p].\n", nxagentDrawableType(pDrawable), + (void *) pDrawable, (void *) nxagentSynchronization.pDrawable); + #endif + + return; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Last synchronized drawable [%p] found. " + "Skipping to the next resource.\n", (void *) nxagentSynchronization.pDrawable); + #endif + + nxagentSynchronization.pDrawable = NULL; + + return; + } + } + + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + /* + * The pixmaps to be synchronized are those + * used as background or used as source of + * any deferred operations for at least 2 + * times. + */ + + if (NXAGENT_SHOULD_SYNCHRONIZE_PIXMAP(pDrawable) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Skipping pixmap at [%p] " + "with usage [%d] background [%d].\n", (void *) pDrawable, + nxagentPixmapUsageCounter((PixmapPtr) pDrawable), + nxagentIsCorruptedBackground((PixmapPtr) pDrawable)); + #endif + + return; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Synchronizing pixmap at [%p] " + "with usage [%d] background [%d].\n", (void *) pDrawable, + nxagentPixmapUsageCounter((PixmapPtr) pDrawable), + nxagentIsCorruptedBackground((PixmapPtr) pDrawable)); + } + #endif + } + else if (NXAGENT_SHOULD_SYNCHRONIZE_WINDOW(pDrawable) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Skipping not visible window at [%p].\n", + (void *) pDrawable); + #endif + + if (shouldClearHiddenRegion == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Clearing out the not visible window " + "at [%p].\n", (void *) pDrawable); + #endif + + nxagentCleanCorruptedDrawable(pDrawable); + } + + return; + } + + /* + * Postpone the synchronization if we went + * out of bandwidth or if the display blocks. + * The pixmap synchronization is more careful + * with bandwidth usage. + */ + +/* +FIXME: This condition sounds only as a + complication, as the break parameters + are already checked while synchroni- + zing the drawable. + + if (breakOnCongestion(*breakMask) == 1 || + (pDrawable -> type == DRAWABLE_PIXMAP && + *breakMask != NEVER_BREAK && nxagentCongestion > 0)) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: WARNING! Breaking the " + "synchronization with congestion [%d] blocking [%d].\n", + nxagentCongestion, nxagentBlocking); + #endif + + nxagentSynchronization.abort = 1; + + return; + } +*/ + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Synchronizing drawable [%s][%p] " + "with geometry (%dx%d).\n", nxagentDrawableType(pDrawable), + (void *) pDrawable, pDrawable -> width, pDrawable -> height); + + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Corrupted extents [%d,%d,%d,%d] " + "with [%ld] rects.\n", nxagentCorruptedRegion(pDrawable) -> extents.x1, + nxagentCorruptedRegion(pDrawable) -> extents.y1, nxagentCorruptedRegion(pDrawable) -> + extents.x2, nxagentCorruptedRegion(pDrawable) -> extents.y2, + REGION_NUM_RECTS(nxagentCorruptedRegion(pDrawable))); + #endif + + /* + * The stored bitmap is destroyed inside + * the synchronization loop, so we have + * to check here its presence to know if + * we can clear the dirty windows. + */ + + shouldClearHiddenRegion = (nxagentDrawableBitmap(pDrawable) == NullPixmap); + + nxagentSynchronizeDrawable(pDrawable, DONT_WAIT, *breakMask, NULL); + + if (nxagentDrawableStatus(pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Drawable [%s][%p] not fully synchronized.\n", + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + /* + * If the remaining corrupted region is on + * an hidden section (not viewable or outside + * of the pixmap's area) of a drawable, + * we can clear it. + */ + + if (nxagentSynchronization.abort == 0 && + shouldClearHiddenRegion == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Clearing out the remaining corrupted " + "[%s] at [%p].\n", nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + nxagentCleanCorruptedDrawable(pDrawable); + } + } +} + +void nxagentSynchronizationLoop(unsigned int mask) +{ + unsigned int breakMask; + + int doRoundRobin; + +/* +FIXME: All drawables should be set as synchronized and + never marked as corrupted while the display is + down. +*/ + if (NXDisplayError(nxagentDisplay) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizationLoop: WARNING! Not synchronizing the drawables " + "with the display down.\n"); + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizationLoop: Synchronizing [%d] windows [%d] pixmaps " + "and [%d] backgrounds with mask [%u].\n", nxagentCorruptedWindows, nxagentCorruptedPixmaps, + nxagentCorruptedBackgrounds, mask); + + fprintf(stderr, "nxagentSynchronizationLoop: Stored bitmaps [%d] windows [%d] pixmaps " + "and [%d] backgrounds.\n", nxagentSynchronization.windowBitmaps, + nxagentSynchronization.pixmapBitmaps, nxagentSynchronization.backgroundBitmaps); + + fprintf(stderr, "nxagentSynchronizationLoop: Starting loops with congestion [%d] " + "blocking [%d].\n", nxagentCongestion, nxagentBlocking); + #endif + + breakMask = mask; + + /* + * The resource counter can be reset if we + * have not aborted the synchronization loop, + * if we are not skipping resources to do + * round-robin and if the bitmaps are all + * synchronized. + */ + + doRoundRobin = (nxagentSynchronization.pDrawable != NULL); + + nxagentSynchronization.abort = 0; + + /* + * Synchronize the windows. + */ + + if (NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_WINDOWS(mask)) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizationLoop: Going to loop through corrupted window resources.\n"); + #endif + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_WINDOW, + nxagentSynchronizeDrawablePredicate, &breakMask); + + #ifdef TEST + + if (nxagentSynchronization.abort == 0 && + nxagentSynchronization.windowBitmaps == 0 && + doRoundRobin == 0) + { + if (nxagentCorruptedWindows > 0) + { + fprintf(stderr, "nxagentSynchronizationLoop: Closing the loop with [%d] " + "corrupted windows.\n", nxagentCorruptedWindows); + } + + nxagentCorruptedWindows = 0; + } + + #endif + } + + /* + * Synchronize the backgrounds. + */ + + if (nxagentSynchronization.abort == 0 && + NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_BACKGROUNDS(mask)) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizationLoop: Going to loop through corrupted background resources.\n"); + #endif + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_BACKGROUND, + nxagentSynchronizeDrawablePredicate, &breakMask); + + #ifdef TEST + + if (nxagentSynchronization.abort == 0 && + nxagentSynchronization.backgroundBitmaps == 0 && + doRoundRobin == 0) + { + if (nxagentCorruptedBackgrounds > 0) + { + fprintf(stderr, "nxagentSynchronizationLoop: Closing the loop with [%d] " + "corrupted backgrounds.\n", nxagentCorruptedBackgrounds); + } + + nxagentCorruptedBackgrounds = 0; + } + + #endif + } + + /* + * If there is bandwidth remaining, synchronize + * the pixmaps. Synchronizing a pixmap doesn't + * produce any visible results. Better is to + * synchronize them on demand, before using the + * pixmap in a copy or in a composite operation. + */ + + if (nxagentSynchronization.abort == 0 && + NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_PIXMAPS(mask)) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizationLoop: Going to loop through corrupted pixmap resources.\n"); + #endif + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_PIXMAP, + nxagentSynchronizeDrawablePredicate, &breakMask); + + + if (nxagentSynchronization.abort == 0 && + nxagentSynchronization.pixmapBitmaps == 0 && + doRoundRobin == 0) + { + #ifdef TEST + + if (nxagentCorruptedPixmaps > 0) + { + fprintf(stderr, "nxagentSynchronizationLoop: Closing the loop with [%d] " + "corrupted pixmaps.\n", nxagentCorruptedPixmaps); + } + + #endif + + nxagentCorruptedPixmaps = 0; + } + + } + + /* + * If the last synchronized drawable has been + * removed, we have to reset the variable sto- + * ring its pointer. + */ + + if (nxagentSynchronization.pDrawable != NULL && + nxagentFindClientResource(serverClient -> index, RT_NX_CORR_WINDOW, + nxagentSynchronization.pDrawable) == 0 && + nxagentFindClientResource(serverClient -> index, RT_NX_CORR_BACKGROUND, + nxagentSynchronization.pDrawable) == 0 && + nxagentFindClientResource(serverClient -> index, RT_NX_CORR_PIXMAP, + nxagentSynchronization.pDrawable) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizationLoop: Synchronization drawable [%p] removed from resources.\n", + (void *) nxagentSynchronization.pDrawable); + #endif + + nxagentSynchronization.pDrawable = NULL; + } + + #ifdef TEST + fprintf(stderr, "nxagentSynchronizationLoop: Closing loops with congestion [%d] " + "blocking [%d].\n", nxagentCongestion, nxagentBlocking); + + fprintf(stderr, "nxagentSynchronizationLoop: There are now [%d] windows [%d] pixmaps " + "and [%d] backgrounds to synchronize.\n", nxagentCorruptedWindows, + nxagentCorruptedPixmaps, nxagentCorruptedBackgrounds); + #endif +} + +RegionPtr nxagentCreateRegion(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int width, int height) +{ + RegionPtr pRegion; + BoxRec box; + + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + + pRegion = REGION_CREATE(pDrawable -> pScreen, &box, 1); + + /* + * Clipping the region. + */ + + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + BoxRec tmpBox; + RegionRec tmpRegion; + + /* + * The region created doesn't need to be clipped + * if it has the pixmap dimensions. + */ + + if (x != 0 || y != 0 || + width != pDrawable -> width || + height != pDrawable -> height) + { + tmpBox.x1 = 0; + tmpBox.y1 = 0; + tmpBox.x2 = pDrawable -> width; + tmpBox.y2 = pDrawable -> height; + + REGION_INIT(pDrawable -> pScreen, &tmpRegion, &tmpBox, 1); + + REGION_INTERSECT(pDrawable -> pScreen, pRegion, &tmpRegion, pRegion); + + REGION_UNINIT(pDrawable -> pScreen, &tmpRegion); + } + } + else + { + /* + * We use the clipList because the borderClip + * contains also parts of the window covered + * by its children. + */ + + REGION_TRANSLATE(pDrawable -> pScreen, pRegion, + pDrawable -> x, pDrawable -> y); + + if (nxagentWindowPriv((WindowPtr) pDrawable) -> hasTransparentChildren == 1) + { + REGION_INTERSECT(pDrawable -> pScreen, pRegion, pRegion, &((WindowPtr) pDrawable) -> borderClip); + } + else + { + REGION_INTERSECT(pDrawable -> pScreen, pRegion, pRegion, &((WindowPtr) pDrawable) -> clipList); + } + + REGION_TRANSLATE(pDrawable -> pScreen, pRegion, + -pDrawable -> x, -pDrawable -> y); + } + + #ifdef TEST + fprintf(stderr, "nxagentCreateRegion: New region created with coordinates [%d,%d,%d,%d].\n", + pRegion -> extents.x1, pRegion -> extents.y1, + pRegion -> extents.x2, pRegion -> extents.y2); + #endif + + /* + * If the pRegion is NIL we don't need + * to intersect it with the GC's clipmask. + */ + + if (REGION_NIL(pRegion) == 0 && + pGC != NULL && pGC -> clientClip != NULL && + pGC -> clientClipType == CT_REGION) + { + RegionRec clipRegion; + + REGION_INIT(pDrawable -> pScreen, &clipRegion, NullBox, 1); + + REGION_COPY(pDrawable -> pScreen, &clipRegion, (RegionPtr) pGC -> clientClip); + + /* + * The clip origin is relative to the origin of + * the destination drawable. The clip mask coor- + * dinates are relative to the clip origin. + */ + + if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0) + { + REGION_TRANSLATE(pDrawable -> pScreen, &clipRegion, pGC -> clipOrg.x, pGC -> clipOrg.y); + } + + #ifdef TEST + fprintf(stderr, "nxagentCreateRegion: Clipping region to the clip mask with coordinates [%d,%d,%d,%d].\n", + clipRegion.extents.x1, clipRegion.extents.y1, + clipRegion.extents.x2, clipRegion.extents.y2); + #endif + + REGION_INTERSECT(pDrawable -> pScreen, pRegion, pRegion, &clipRegion); + + REGION_UNINIT(pDrawable -> pScreen, &clipRegion); + } + + return pRegion; +} + +void nxagentMarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion) +{ + int x; + int y; + int width; + int height; + + if (pRegion != NullRegion && REGION_NIL(pRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentMarkCorruptedRegion: Region [%d,%d,%d,%d] is nil. Skipping operation.\n", + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2); + #endif + + return; + } + + /* + * If the drawable was synchronized, the counter + * reporting the number of corrupted drawables + * must be increased. Moreover the corrupted ti- + * mestamp must be set. + */ + + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + if (pDrawable -> type == DRAWABLE_WINDOW) + { + nxagentAllocateCorruptedResource(pDrawable, RT_NX_CORR_WINDOW); + } + + nxagentSetCorruptedTimestamp(pDrawable); + } + + if (pRegion == NullRegion) + { + x = 0; + y = 0; + + width = pDrawable -> width; + height = pDrawable -> height; + + #ifdef TEST + fprintf(stderr, "nxagentMarkCorruptedRegion: Fully invalidating %s [%p] with " + "coordinates [%d,%d][%d,%d].\n", nxagentDrawableType(pDrawable), + (void *) pDrawable, x, y, width, height); + #endif + + pRegion = nxagentCreateRegion(pDrawable, NULL, x, y, width, height); + + nxagentValidateSplit(pDrawable, pRegion); + + REGION_UNION(pDrawable -> pScreen, nxagentCorruptedRegion(pDrawable), + nxagentCorruptedRegion(pDrawable), pRegion); + + nxagentFreeRegion(pDrawable, pRegion); + } + else + { + #ifdef TEST + + x = pRegion -> extents.x1; + y = pRegion -> extents.y1; + + width = pRegion -> extents.x2 - pRegion -> extents.x1; + height = pRegion -> extents.y2 - pRegion -> extents.y1; + + fprintf(stderr, "nxagentMarkCorruptedRegion: Partly invalidating %s [%p] with " + "coordinates [%d,%d][%d,%d].\n", nxagentDrawableType(pDrawable), + (void *) pDrawable, x, y, width, height); + + #endif + + nxagentValidateSplit(pDrawable, pRegion); + + REGION_UNION(pDrawable -> pScreen, nxagentCorruptedRegion(pDrawable), + nxagentCorruptedRegion(pDrawable), pRegion); + } +} + +void nxagentUnmarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion) +{ + int oldStatus; + + if (pRegion != NullRegion && REGION_NIL(pRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentUnmarkCorruptedRegion: Region [%d,%d,%d,%d] is nil. Skipping operation.\n", + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2); + #endif + + return; + } + + oldStatus = nxagentDrawableStatus(pDrawable); + + if (oldStatus == Synchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentUnmarkCorruptedRegion: Drawable %s [%p] already synchronized.\n", + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + return; + } + + if (pRegion == NullRegion) + { + #ifdef TEST + fprintf(stderr, "nxagentUnmarkCorruptedRegion: Fully validating %s [%p].\n", + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + nxagentValidateSplit(pDrawable, NULL); + + REGION_EMPTY(pDrawable -> pScreen, nxagentCorruptedRegion(pDrawable)); + } + else + { + #ifdef TEST + + fprintf(stderr, "nxagentUnmarkCorruptedRegion: Validating %s [%p] with region [%d,%d,%d,%d].\n", + nxagentDrawableType(pDrawable), (void *) pDrawable, + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2); + + #endif + + nxagentValidateSplit(pDrawable, pRegion); + + REGION_SUBTRACT(pDrawable -> pScreen, nxagentCorruptedRegion(pDrawable), + nxagentCorruptedRegion(pDrawable), pRegion); + } + + /* + * If the drawable becomes synchronized, the + * counter reporting the number of corrupted + * drawables must be decreased. Moreover the + * corrupted timestamp must be reset. + */ + + if (oldStatus == NotSynchronized && + nxagentDrawableStatus(pDrawable) == Synchronized) + { + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_BACKGROUND); + + nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_PIXMAP); + + nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> containTrapezoids = 0; + } + else + { + nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_WINDOW); + } + + nxagentResetCorruptedTimestamp(pDrawable); + + /* + * If the resource is no longer dirty, + * the associated bitmap is destroyed. + */ + + if (nxagentDrawableBitmap(pDrawable) != NullPixmap) + { + nxagentDestroyDrawableBitmap(pDrawable); + } + } +} + +void nxagentMoveCorruptedRegion(WindowPtr pWin, unsigned int mask) +{ + /* + * If a window is resized, its corrupted + * region is moved according to the bit + * gravity. + */ + + if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized) + { + if (((mask & CWHeight) && nxagentWindowPriv(pWin) -> height != pWin -> drawable.height) || + ((mask & CWWidth) && nxagentWindowPriv(pWin) -> width != pWin -> drawable.width)) + { + int nx, ny; + + GravityTranslate(0, 0, + nxagentWindowPriv(pWin) -> x - pWin -> origin.x + wBorderWidth(pWin), + nxagentWindowPriv(pWin) -> y - pWin -> origin.y + wBorderWidth(pWin), + pWin -> drawable.width - nxagentWindowPriv(pWin) -> width, + pWin -> drawable.height - nxagentWindowPriv(pWin) -> height, + pWin -> bitGravity, &nx, &ny); + + #ifdef TEST + fprintf(stderr, "nxagentMoveCorruptedRegion: Moving the corrupted region to [%d,%d] for window [%p].\n", + nx, ny, (void *) pWin); + #endif + + REGION_TRANSLATE(pWin -> pScreen, nxagentCorruptedRegion((DrawablePtr) pWin), + nx, ny); + + /* + * Having moved the corrupted region, we + * need to invalidate the pending commits + * or otherwise the image will fall in + * the wrong area. + */ + + nxagentValidateSplit((DrawablePtr) pWin, NULL); + + + /* + * The window reconfiguration invalidates + * the synchronization bitmap. + */ + + nxagentDestroyDrawableBitmap((DrawablePtr) pWin); + } + } +} + +/* + * The DDX layer uses an 'Y-X banding' representation of + * regions: it sorts all rectangles composing a region + * using first the y-dimension, than the x-dimension; mo- + * reover it organizes the rectangles in 'bands' sharing + * the same y-dimension. This representation does not mi- + * nimize the number of rectangles. For example, the fol- + * lowing region has 4 rectangles: + * + * +-----------+ + * | | +---+ + * | A | | B | + * | | +---+ + * +-----------+ + * + * The rectangle 'B' creates a band which splits the rec- + * tangle A in 3 parts, for a total of 3 bands. The num- + * ber of rectangles composing the region is 4. + * + * This kind of representation is not advisable for the + * lazy synchronization because, in the example above, + * the nxagent had to send 4 put images instead of 2. + * + * To minimize the problem we use the following function: + * by traversing the list of rectangles we merge all bo- + * xes with same x coordinates and coincident y, in order + * to create an X-Y banding. + * + * Be careful: all the coordinates of boxes merged are + * set to 0, so take care of this when looping through + * the box list returned by this function. + */ + +BoxPtr nxagentGetOptimizedRegionBoxes(RegionPtr pRegion) +{ + BoxPtr pBox; + + BoxRec boxExtents; + + int nBox; + int i, j; + + #ifdef DEBUG + int nBoxOptim; + #endif + + pBox = REGION_RECTS(pRegion); + + nBox = REGION_NUM_RECTS(pRegion); + + #ifdef TEST + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Going to optimize region at [%p] with [%d] rects.\n", + (void *) pRegion, nBox); + #endif + + if (nBox <= 1) + { + return pBox; + } + + #ifdef DEBUG + nBoxOptim = nBox; + #endif + + /* + * The boxes are now grouped to grown as much + * as possible, using their overlapping vertex + * as rule. + */ + + for (i = 0; i < nBox; i++) + { + /* + * If the coordinates are (0,0) the box + * has been already merged, so we can skip + * it. + */ + + if (pBox[i].x1 == 0 && pBox[i].y1 == 0 && + pBox[i].x2 == 0 && pBox[i].y2 == 0) + { + continue; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Referential box [%d] has coordinates [%d,%d,%d,%d].\n", + i, pBox[i].x1, pBox[i].y1, pBox[i].x2, pBox[i].y2); + #endif + + #ifdef ADVANCED_BOXES_DEFRAG + + boxExtents.x1 = pBox[i].x1; + boxExtents.y1 = pBox[i].y1; + boxExtents.x2 = pBox[i].x2; + + #endif + + boxExtents.y2 = pBox[i].y2; + + for (j = i+1; j < nBox; j++) + { + if (pBox[j].x1 == 0 && pBox[j].y1 == 0 && + pBox[j].x2 == 0 && pBox[j].y2 == 0) + { + continue; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Mergeable box [%d] has coordinates [%d,%d,%d,%d].\n", + j, pBox[j].x1, pBox[j].y1, pBox[j].x2, pBox[j].y2); + #endif + + /* + * Each consequent box is merged if its + * higher side overlaps the lower side + * of current box. + * In case of ADVANCED_BOXES_DEFRAG the higher + * side must be included within a range + * defined by INCLUDE_MARGIN. + */ + + #ifndef ADVANCED_BOXES_DEFRAG + + if (pBox[j].y1 == boxExtents.y2 && + pBox[j].x1 == pBox[i].x1 && + pBox[j].x2 == pBox[i].x2) + + #else + + if (pBox[j].x1 > boxExtents.x1 - INCLUDE_MARGIN && + pBox[j].x1 < boxExtents.x1 + INCLUDE_MARGIN && + pBox[j].y1 > boxExtents.y2 - INCLUDE_MARGIN && + pBox[j].y1 < boxExtents.y2 + INCLUDE_MARGIN && + pBox[j].x2 > boxExtents.x2 - INCLUDE_MARGIN && + pBox[j].x2 < boxExtents.x2 + INCLUDE_MARGIN) + + #endif + { + #ifdef DEBUG + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Going to merge box at [%d] with box at [%d].\n", + j, i); + #endif + + #ifdef ADVANCED_BOXES_DEFRAG + + if (pBox[j].x1 < boxExtents.x1) + { + boxExtents.x1 = pBox[j].x1; + } + + if (pBox[j].x2 > boxExtents.x2) + { + boxExtents.x2 = pBox[j].x2; + } + + if (pBox[j].y1 < boxExtents.y1) + { + boxExtents.y1 = pBox[j].y1; + } + + #endif + + if (pBox[j].y2 > boxExtents.y2) + { + boxExtents.y2 = pBox[j].y2; + } + + /* + * By appending a box to another, we have + * to remove it from the box list. We do + * this by setting its coordinates to (0,0) + * and by checking their value in the main + * loop. + */ + + pBox[j].x1 = pBox[j].y1 = pBox[j].x2 = pBox[j].y2 = 0; + + #ifdef DEBUG + nBoxOptim--; + #endif + } + } + + /* + * Extend the box height. + */ + + #ifdef ADVANCED_BOXES_DEFRAG + + pBox[i].x1 = boxExtents.x1; + pBox[i].y1 = boxExtents.y1; + pBox[i].x2 = boxExtents.x2; + + #endif + + pBox[i].y2 = boxExtents.y2; + } + + #ifdef ADVANCED_BOXES_DEFRAG + + /* + * The new list need to be validated to + * avoid boxes overlapping. This code may + * be improved to remove also the partial- + * ly overlapping boxes. + */ + + for (i = 0; i < nBox; i++) + { + if (pBox[i].x1 == 0 && pBox[i].y1 == 0 && + pBox[i].x2 == 0 && pBox[i].y2 == 0) + { + continue; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Referential box [%d] has coordinates [%d,%d,%d,%d].\n", + i, pBox[i].x1, pBox[i].y1, pBox[i].x2, pBox[i].y2); + #endif + + boxExtents.x1 = pBox[i].x1; + boxExtents.y1 = pBox[i].y1; + boxExtents.x2 = pBox[i].x2; + boxExtents.y2 = pBox[i].y2; + + for (j = i+1; j < nBox; j++) + { + if (pBox[j].x1 == 0 && pBox[j].y1 == 0 && + pBox[j].x2 == 0 && pBox[j].y2 == 0) + { + continue; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Mergeable box [%d] has coordinates [%d,%d,%d,%d].\n", + j, pBox[j].x1, pBox[j].y1, pBox[j].x2, pBox[j].y2); + #endif + + if ((boxExtents.x1 <= pBox[j].x1 && + boxExtents.x2 >= pBox[j].x2 && + boxExtents.y1 <= pBox[j].y1 && + boxExtents.y2 >= pBox[j].y2)) + { + /* + * If a box is completely inside + * another, we set its coordinates + * to 0 to consider it as merged. + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Going to merge box [%d,%d,%d,%d] " + "with its box container [%d,%d,%d,%d].\n", pBox[j].x1, pBox[j].y1, + pBox[j].x2, pBox[j].y2, boxExtents.x1, boxExtents.y1, boxExtents.y1, + boxExtents.y2); + #endif + + pBox[j].x1 = pBox[j].y1 = pBox[j].x2 = pBox[j].y2 = 0; + + #ifdef DEBUG + nBoxOptim--; + #endif + } + } + } + + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Original boxes number [%d] Optimized boxes number [%d].\n", + nBox, nBoxOptim); + #endif + + return pBox; +} + +unsigned long nxagentGetColor(DrawablePtr pDrawable, int xPixel, int yPixel) +{ + XImage *ximage; + Visual *pVisual; + char *data; + + int depth, format, length; + int leftPad = 0; + unsigned long pixel; + + depth = pDrawable -> depth; + format = (depth == 1) ? XYPixmap : ZPixmap; + length = nxagentImageLength(1, 1, format, leftPad, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentGetColor: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + return -1; + } + + pVisual = nxagentImageVisual(pDrawable, depth); + + if (pVisual == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentGetColor: WARNING! Visual not found. Using default visual.\n"); + #endif + + pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual; + } + + fbGetImage(pDrawable, xPixel, yPixel, 1, 1, format, AllPlanes, data); + + ximage = XCreateImage(nxagentDisplay, pVisual, depth, format, leftPad, (char *) data, + 1, 1, BitmapPad(nxagentDisplay), + nxagentImagePad(1, format, leftPad, 1)); + + if (ximage == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentGetColor: WARNING! Failed to create the XImage.\n"); + #endif + + xfree(data); + + return -1; + } + + pixel = XGetPixel(ximage, 0, 0); + + XDestroyImage(ximage); + + return pixel; +} + +/* + * This function could be used to determine + * the ClearArea color of corrupted regions + * on screen. + */ + +unsigned long nxagentGetRegionColor(DrawablePtr pDrawable, RegionPtr pRegion) +{ + int xPicker, yPicker; + + if (REGION_NIL(pRegion) == 1) + { + return nxagentGetDrawableColor(pDrawable); + } + + /* + * The pixel used as reference is the first + * outer pixel at the bottom right corner + * of corrupted region extents. + */ + + xPicker = pRegion -> extents.x2 + 1; + + if (xPicker > pDrawable -> width) + { + xPicker = pDrawable -> width; + } + + yPicker = pRegion -> extents.y2 + 1; + + if (yPicker > pDrawable -> height) + { + yPicker = pDrawable -> height; + } + + return nxagentGetColor(pDrawable, xPicker, yPicker); +} + +unsigned long nxagentGetDrawableColor(DrawablePtr pDrawable) +{ + int xPicker, yPicker; + + /* + * The pixel used to determine the co- + * lor of a drawable is at coordinates + * (x + width - 4, y + 4). + */ + + xPicker = pDrawable -> width - 4; + + yPicker = 4; + + return nxagentGetColor(pDrawable, xPicker, yPicker); +} + +void nxagentClearRegion(DrawablePtr pDrawable, RegionPtr pRegion) +{ + WindowPtr pWin; + BoxPtr pBox; + + unsigned long color; + unsigned long backupPixel = 0; + int nBox, i; + int restore; + + #ifdef DEBUG + static int nBoxCleared; + #endif + + if (pDrawable -> type != DRAWABLE_WINDOW) + { + #ifdef TEST + fprintf(stderr, "nxagentClearRegion: Cannot clear a pixmap. Exiting.\n"); + #endif + + return; + } + + if (pRegion == NullRegion || REGION_NIL(pRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentClearRegion: The region is empty. Exiting.\n"); + #endif + + return; + } + + pWin = (WindowPtr) pDrawable; + + restore = 0; + + /* + * If the window has already a background, we + * can hope it will be nice. + */ + + if (pWin -> backgroundState != None) + { + #ifdef DEBUG + fprintf(stderr, "nxagentClearRegion: Window at [%p] has background state [%u].\n", + (void *) pWin, pWin -> backgroundState); + #endif + } + else + { + /* + * Save the original state. + */ + + backupPixel = pWin -> background.pixel; + + color = nxagentGetDrawableColor((DrawablePtr) pWin); + + if (color == -1) + { + color = 0xffffff; + } + + pWin -> backgroundState = BackgroundPixel; + pWin -> background.pixel = color; + + nxagentChangeWindowAttributes(pWin, CWBackPixel); + + #ifdef DEBUG + fprintf(stderr, "nxagentClearRegion: Window at [%p] now has pixel background [%ld].\n", + (void *) pWin, color); + #endif + + restore = 1; + } + + pBox = nxagentGetOptimizedRegionBoxes(pRegion); + + nBox = REGION_NUM_RECTS(pRegion); + + for (i = 0; i < nBox; i++) + { + if (pBox[i].x1 == 0 && pBox[i].y1 == 0 && + pBox[i].x2 == 0 && pBox[i].y2 == 0) + { + continue; + } + + XClearArea(nxagentDisplay, nxagentWindow(pWin), pBox[i].x1, pBox[i].y1, + pBox[i].x2 - pBox[i].x1, pBox[i].y2 - pBox[i].y1, False); + + #ifdef DEBUG + nBoxCleared++; + #endif + } + + /* + * Restore the old state. + */ + + if (restore == 1) + { + pWin -> backgroundState = None; + pWin -> background.pixel = backupPixel; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentClearRegion: Number of cleared boxes is [%d].\n", nBoxCleared); + #endif +} + +void nxagentFillRemoteRegion(DrawablePtr pDrawable, RegionPtr pRegion) +{ + GCPtr pGC; + BoxPtr pBox; + XRectangle *pRects; + + int nrects; + int i; + + if (REGION_NIL(pRegion) == 1) + { + return; + } + + pGC = nxagentGetGraphicContext(pDrawable); + + nrects = REGION_NUM_RECTS(pRegion); + + #ifdef TEST + fprintf(stderr, "nxagentFillRemoteRegion: Going to fill remote region [%d,%d,%d,%d] rects [%d] with color [%lu].\n", + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2, + nrects, pGC -> fgPixel); + #endif + + if (nrects == 1) + { + XFillRectangle(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + pRegion -> extents.x1, pRegion -> extents.y1, + pRegion -> extents.x2 - pRegion -> extents.x1, + pRegion -> extents.y2 - pRegion -> extents.y1); + } + else + { + pBox = REGION_RECTS(pRegion); + + pRects = xalloc(nrects * sizeof(XRectangle)); + + for (i = 0; i < nrects; i++) + { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + + XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + pRects, nrects); + + xfree(pRects); + } +} + +int nxagentDestroyCorruptedWindowResource(pointer p, XID id) +{ + #ifdef TEST + fprintf(stderr, "nxagentDestroyCorruptedWindowResource: Removing corrupted window [%p] from resources.\n", + (void *) p); + #endif + + nxagentWindowPriv((WindowPtr) p) -> corruptedId = None; + + return 1; +} + +int nxagentDestroyCorruptedPixmapResource(pointer p, XID id) +{ + #ifdef TEST + fprintf(stderr, "nxagentDestroyCorruptedPixmapResource: Removing corrupted pixmap [%p] from resources.\n", + (void *) p); + #endif + + nxagentPixmapPriv((PixmapPtr) p) -> corruptedId = None; + + return 1; +} + +int nxagentDestroyCorruptedBackgroundResource(pointer p, XID id) +{ + #ifdef TEST + fprintf(stderr, "nxagentDestroyCorruptedBackgroundResource: Removing corrupted pixmap background [%p] from resources.\n", + (void *) p); + #endif + + nxagentPixmapPriv((PixmapPtr) p) -> corruptedBackgroundId = None; + + return 1; +} + +void nxagentPointsToDirtyRegion(DrawablePtr pDrawable, int mode, + int nPoints, xPoint *pPoints) +{ + RegionPtr pRegion; + RegionRec tmpRegion; + BoxRec box, extents; + + xPoint *xp; + int np; + + np = nPoints; + xp = pPoints; + + pRegion = REGION_CREATE(pDrawable -> pScreen, NullBox, 1); + + while (np--) + { + if (CoordModePrevious) + { + box.x1 = box.x2 = (xp-1) -> x + xp -> x; + box.y1 = box.y2 = (xp-1) -> y + xp -> y; + } + else + { + box.x1 = box.x2 = xp -> x; + box.y1 = box.y2 = xp -> y; + } + + #ifdef TEST + fprintf(stderr, "nxagentPointsToDirtyRegion: Adding the point (%d,%d) to the dirty region.\n", + box.x1, box.y1); + #endif + + /* + * By using REGION_APPEND() and REGION_VALIDATE() + * this loop could become less expensive. + */ + + REGION_INIT(pDrawable -> pScreen, &tmpRegion, &box, 1); + + REGION_UNION(pDrawable -> pScreen, pRegion, pRegion, &tmpRegion); + + REGION_UNINIT(pDrawable -> pScreen, &tmpRegion); + + xp++; + } + + extents = *REGION_EXTENTS(pDrawable -> pScreen, pRegion); + + REGION_RESET(pDrawable -> pScreen, pRegion, &extents); + + #ifdef TEST + fprintf(stderr, "nxagentPointsToDirtyRegion: The resulting dirty region has [%ld] rects and" + " extents (%d,%d,%d,%d).\n", REGION_NUM_RECTS(pRegion), extents.x1, + extents.y1, extents.x2, extents.y2); + #endif + + nxagentMarkCorruptedRegion(pDrawable, pRegion); + + REGION_DESTROY(pDrawable -> pScreen, pRegion); +} + +#ifdef DUMP + +#define USE_MULTIPLE_COLORS + +void nxagentCorruptedRegionOnWindow(void *p0, XID x, void *p2) +{ + WindowPtr pWin = (WindowPtr) p0; + RegionPtr clipRegion; + RegionRec visRegion; + BoxPtr pBox; + + XlibGC gc; + XGCValues value; + + static unsigned long color = 0xff000000; + int nrectangles; + int i; + + /* + * There are no regions to draw. + */ + + if (nxagentDrawableStatus((DrawablePtr) pWin) == Synchronized) + { + return; + } + + /* + * The window is not visible. + */ + + if (nxagentWindowIsVisible(pWin) == 0) + { + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentCorruptedRegionOnWindow: Going to draw on window at [%p].\n", + (void *) pWin); + #endif + + clipRegion = nxagentCreateRegion((DrawablePtr) pWin, NULL, 0, 0, + pWin -> drawable.width, pWin -> drawable.height); + + REGION_INIT(pWin -> drawable.pScreen, &visRegion, NullBox, 1); + + REGION_INTERSECT(pWin -> drawable.pScreen, &visRegion, clipRegion, nxagentCorruptedRegion((DrawablePtr) pWin)); + + nxagentFreeRegion(pWin -> drawable.pScreen, clipRegion); + + if (REGION_NIL(&visRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentCorruptedRegionOnWindow: The corrupted region of window at [%p] is hidden.\n", + (void *) pWin); + #endif + + REGION_UNINIT(pWin -> drawable.pScreen, &visRegion); + + return; + } + + nxagentClearRegion((DrawablePtr) pWin, &visRegion); + + #ifdef USE_MULTIPLE_COLORS + + color += nxagentWindow(pWin) * 5; + + if (color == 0 || color == 0xffffffff) + { + color = 0xff000000; + } + + #endif + + value.foreground = color; + value.subwindow_mode = IncludeInferiors; + + gc = XCreateGC(nxagentDisplay, nxagentWindow(pWin), GCForeground | GCSubwindowMode, &value); + + nrectangles = REGION_NUM_RECTS(&visRegion); + + #ifdef TEST + fprintf(stderr, "nxagentCorruptedRegionOnWindow: Going to draw the region with extents [%d,%d,%d,%d] and [%d] rects.\n", + visRegion.extents.x1, visRegion.extents.y1, visRegion.extents.x2, visRegion.extents.y2, + nrectangles); + #endif + + pBox = nxagentGetOptimizedRegionBoxes(&visRegion); + + for (i = 0; i < nrectangles; i++) + { + if (pBox[i].x1 == 0 && pBox[i].y1 == 0 && + pBox[i].x2 == 0 && pBox[i].y2 == 0) + { + continue; + } + + XDrawRectangle(nxagentDisplay, nxagentWindow(pWin), gc, + pBox[i].x1, pBox[i].y1, pBox[i].x2 - pBox[i].x1 - 1, + pBox[i].y2 - pBox[i].y1 - 1); + } + + XFreeGC(nxagentDisplay, gc); + + REGION_UNINIT(pWin -> drawable.pScreen, &visRegion); +} + +void nxagentRegionsOnScreen() +{ + FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_WINDOW, + nxagentCorruptedRegionOnWindow, NULL); +} + +#endif + +/* + * If the synchronization loop breaks and the + * drawable synchronization cannot be completed, + * the remaining data is stored in a bitmap. + * The synchronization loop is then restarted + * using the bitmap as source instead of the + * drawable. + */ + +void nxagentCreateDrawableBitmap(DrawablePtr pDrawable) +{ + PixmapPtr pBitmap; + GCPtr pGC = NULL; + RegionPtr pClipRegion = NullRegion; + + char *data = NULL; + + int x, y; + int w, h; + int length, format; + int saveTrap; + + #ifdef TEST + fprintf(stderr, "nxagentCreateDrawableBitmap: Creating synchronization bitmap for drawable at [%p].\n", + (void *) pDrawable); + #endif + + /* + * The bitmap is created only in the + * nxagent. + */ + + saveTrap = nxagentGCTrap; + + nxagentGCTrap = 1; + + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentCreateDrawableBitmap: The drawable is already synchronized. Skipping bitmap creation.\n"); + #endif + + goto nxagentCreateDrawableBitmapEnd; + } + + /* + * Should create a function to append + * a bitmap to another, instead of de- + * stroy the old one. + */ + + if (nxagentDrawableBitmap(pDrawable) != NullPixmap) + { + #ifdef WARNING + fprintf(stderr, "nxagentCreateDrawableBitmap: WARNING! Going to replace the bitmap at [%p] with corrupted [%d,%d,%d,%d].\n", + (void *) nxagentDrawableBitmap(pDrawable), + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x1, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y1, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x2, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y2); + #endif + + nxagentDestroyDrawableBitmap(pDrawable); + } + + /* + * Clipping to the visible area. + */ + + pClipRegion = nxagentCreateRegion(pDrawable, NULL, 0, 0, pDrawable -> width, pDrawable -> height); + + REGION_INTERSECT(pDrawable -> pScreen, pClipRegion, pClipRegion, nxagentCorruptedRegion(pDrawable)); + + if (REGION_NIL(pClipRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentCreateDrawableBitmap: The corrupted region is not visible. Skipping bitmap creation.\n"); + #endif + + goto nxagentCreateDrawableBitmapEnd; + } + + pBitmap = nxagentCreatePixmap(pDrawable -> pScreen, pDrawable -> width, pDrawable -> height, pDrawable -> depth); + + pGC = GetScratchGC(pBitmap -> drawable.depth, pBitmap -> drawable.pScreen); + + ValidateGC((DrawablePtr) pBitmap, pGC); + + x = pClipRegion -> extents.x1; + y = pClipRegion -> extents.y1; + w = pClipRegion -> extents.x2 - pClipRegion -> extents.x1; + h = pClipRegion -> extents.y2 - pClipRegion -> extents.y1; + + data = nxagentAllocateImageData(w, h, pDrawable -> depth, &length, &format); + + if (data == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentCreateDrawableBitmap: Cannot allocate memory for the bitmap data.\n"); + #endif + + nxagentDestroyPixmap(pBitmap); + + goto nxagentCreateDrawableBitmapEnd; + } + + nxagentGetImage(pDrawable, x, y, w, h, format, AllPlanes, data); + + nxagentPutImage((DrawablePtr) pBitmap, pGC, pBitmap -> drawable.depth, x, y, w, h, + 0, format, data); + + REGION_UNION(pDrawable -> pScreen, nxagentCorruptedRegion((DrawablePtr) pBitmap), + nxagentCorruptedRegion((DrawablePtr) pBitmap), pClipRegion); + + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> synchronizationBitmap = pBitmap; + + if (nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1) + { + nxagentSynchronization.backgroundBitmaps++; + } + else + { + nxagentSynchronization.pixmapBitmaps++; + } + } + else + { + nxagentWindowPriv((WindowPtr) pDrawable) -> synchronizationBitmap = pBitmap; + + nxagentSynchronization.windowBitmaps++; + } + + #ifdef TEST + fprintf(stderr, "nxagentCreateDrawableBitmap: Drawable [%p] has bitmap at [%p] with corrupted [%d,%d,%d,%d].\n", + (void *) pDrawable, (void *) nxagentDrawableBitmap(pDrawable), + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x1, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y1, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x2, + nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y2); + #endif + +nxagentCreateDrawableBitmapEnd: + + nxagentGCTrap = saveTrap; + + if (pClipRegion != NullRegion) + { + nxagentFreeRegion(pDrawable, pClipRegion); + } + + if (data != NULL) + { + xfree(data); + } + + if (pGC != NULL) + { + FreeScratchGC(pGC); + } +} + +void nxagentDestroyDrawableBitmap(DrawablePtr pDrawable) +{ + if (nxagentDrawableBitmap(pDrawable) != NullPixmap) + { + #ifdef TEST + fprintf(stderr, "nxagentDestroyDrawableBitmap: Destroying bitmap for drawable at [%p].\n", + (void *) pDrawable); + #endif + + nxagentDestroyPixmap(nxagentDrawableBitmap(pDrawable)); + + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> synchronizationBitmap = NullPixmap; + + if (nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1) + { + nxagentSynchronization.backgroundBitmaps--; + } + else + { + nxagentSynchronization.pixmapBitmaps--; + } + } + else + { + nxagentWindowPriv((WindowPtr) pDrawable) -> synchronizationBitmap = NullPixmap; + + nxagentSynchronization.windowBitmaps--; + } + } +} + +void nxagentIncreasePixmapUsageCounter(PixmapPtr pPixmap) +{ + if (nxagentDrawableStatus((DrawablePtr) pPixmap) == Synchronized) + { + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentIncreasePixmapUsageCounter: Pixmap usage counter was [%d].\n", + nxagentPixmapUsageCounter(pPixmap)); + #endif + + nxagentPixmapUsageCounter(pPixmap) += 1; + + nxagentAllocateCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP); +} + +void nxagentAllocateCorruptedResource(DrawablePtr pDrawable, RESTYPE type) +{ + PixmapPtr pRealPixmap; + + if (nxagentSessionState == SESSION_DOWN) + { + #ifdef TEST + fprintf(stderr, "nxagentAllocateCorruptedResource: WARNING! Not allocated corrupted resource " + "[%s][%p] with the display down.\n", nxagentDrawableType(pDrawable), + (void *) pDrawable); + #endif + + return; + } + + if (type == RT_NX_CORR_WINDOW) + { + if (nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentAllocateCorruptedResource: New resource at [%p]. Corrupted " + "windows counter was [%d].\n", (void *) pDrawable, nxagentCorruptedWindows); + #endif + + nxagentCorruptedWindows++; + + nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId = FakeClientID(serverClient -> index); + + AddResource(nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId, RT_NX_CORR_WINDOW, + (pointer) pDrawable); + } + } + else if (type == RT_NX_CORR_BACKGROUND) + { + pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable); + + if (nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId == 0) + { + /* + * When a pixmap is added to the background + * corrupted resources, it must be removed + * from the pixmap corrupted resources. + */ + + nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_PIXMAP); + + #ifdef TEST + fprintf(stderr, "nxagentAllocateCorruptedResource: New resource at [%p]. Corrupted " + "backgrounds counter was [%d].\n", (void *) pDrawable, nxagentCorruptedBackgrounds); + #endif + + nxagentCorruptedBackgrounds++; + + nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId = FakeClientID(serverClient -> index); + + AddResource(nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId, RT_NX_CORR_BACKGROUND, + (pointer) pRealPixmap); + } + } + else if (type == RT_NX_CORR_PIXMAP) + { + /* + * The shared memory pixmaps are always dirty + * and shouldn't be synchronized. + */ + + if (nxagentPixmapUsageCounter((PixmapPtr) pDrawable) >= MINIMUM_PIXMAP_USAGE_COUNTER && + nxagentIsShmPixmap((PixmapPtr) pDrawable) == 0) + { + pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable); + + if (nxagentPixmapPriv(pRealPixmap) -> corruptedId == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentAllocateCorruptedResource: New resource at [%p]. Corrupted " + "pixmaps counter was [%d].\n", (void *) pDrawable, nxagentCorruptedPixmaps); + #endif + + nxagentCorruptedPixmaps++; + + nxagentPixmapPriv(pRealPixmap) -> corruptedId = FakeClientID(serverClient -> index); + + AddResource(nxagentPixmapPriv(pRealPixmap) -> corruptedId, RT_NX_CORR_PIXMAP, + (pointer) pRealPixmap); + } + } + } +} + +void nxagentDestroyCorruptedResource(DrawablePtr pDrawable, RESTYPE type) +{ + PixmapPtr pRealPixmap; + + if (type == RT_NX_CORR_WINDOW) + { + if (nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDestroyCorruptedResource: Removing resource at [%p]. Corrupted " + "windows counter was [%d].\n", (void *) pDrawable, nxagentCorruptedWindows); + #endif + + if (nxagentCorruptedWindows > 0) + { + nxagentCorruptedWindows--; + } + + FreeResource(nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId, RT_NONE); + + if (nxagentSynchronization.pDrawable == pDrawable) + { + nxagentSynchronization.pDrawable = NULL; + } + } + } + else if (type == RT_NX_CORR_BACKGROUND) + { + pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable); + + if (nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDestroyCorruptedResource: Removing resource at [%p]. Corrupted " + "backgrounds counter was [%d].\n", (void *) pDrawable, nxagentCorruptedBackgrounds); + #endif + + if (nxagentCorruptedBackgrounds > 0) + { + nxagentCorruptedBackgrounds--; + } + + FreeResource(nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId, RT_NONE); + + if (nxagentSynchronization.pDrawable == pDrawable) + { + nxagentSynchronization.pDrawable = NULL; + } + } + } + else if (type == RT_NX_CORR_PIXMAP) + { + pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable); + + if (nxagentPixmapPriv(pRealPixmap) -> corruptedId != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDestroyCorruptedResource: Removing resource at [%p]. Corrupted " + "pixmaps counter was [%d].\n", (void *) pDrawable, nxagentCorruptedPixmaps); + #endif + + if (nxagentCorruptedPixmaps > 0) + { + nxagentCorruptedPixmaps--; + } + + FreeResource(nxagentPixmapPriv(pRealPixmap) -> corruptedId, RT_NONE); + + if (nxagentSynchronization.pDrawable == pDrawable) + { + nxagentSynchronization.pDrawable = NULL; + } + } + } +} + +void nxagentCleanCorruptedDrawable(DrawablePtr pDrawable) +{ + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentCleanCorruptedDrawable: Clearing out the corrupted drawable [%s][%p].\n", + nxagentDrawableType(pDrawable), (void *) pDrawable); + #endif + + nxagentUnmarkCorruptedRegion(pDrawable, NullRegion); + + if (nxagentDrawableBitmap(pDrawable) != NullPixmap) + { + nxagentDestroyDrawableBitmap(pDrawable); + } +} + +void nxagentUnmarkExposedRegion(WindowPtr pWin, RegionPtr pRegion, RegionPtr pOther) +{ + RegionRec clipRegion; + + if (pRegion != NullRegion && REGION_NIL(pRegion) == 0 && + nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized) + { + REGION_INIT(pWin -> drawable.pScreen, &clipRegion, NullBox, 1); + + REGION_COPY(pWin -> drawable.pScreen, &clipRegion, pRegion); + + if (pOther != NullRegion && REGION_NIL(pOther) == 0) + { + REGION_UNION(pWin -> drawable.pScreen, &clipRegion, &clipRegion, pOther); + } + + REGION_TRANSLATE(pWin -> drawable.pScreen, &clipRegion, -pWin -> drawable.x, -pWin -> drawable.y); + + #ifdef TEST + fprintf(stderr, "nxagentUnmarkExposedRegion: Validating expose region [%d,%d,%d,%d] " + "on window [%p].\n", clipRegion.extents.x1, clipRegion.extents.y1, + clipRegion.extents.x2, clipRegion.extents.y2, (void *) pWin); + #endif + + nxagentUnmarkCorruptedRegion((DrawablePtr) pWin, &clipRegion); + + REGION_UNINIT(pWin -> drawable.pScreen, &clipRegion); + } +} + +int nxagentSynchronizationPredicate() +{ + if (nxagentCorruptedWindows == 0 && + nxagentCorruptedBackgrounds == 0 && + nxagentCorruptedPixmaps == 0) + { + return NotNeeded; + } + + if (nxagentBlocking == 0 && + nxagentCongestion <= 4 && + nxagentReady == 0 && + nxagentUserInput(NULL) == 0) + { + return Needed; + } + + /* + * If there are resources to synchronize + * but the conditions to start the loop + * are not satisfied, a little delay is + * requested to check for a new loop as + * soon as possible. + */ + + return Delayed; +} + +void nxagentSendBackgroundExpose(WindowPtr pWin, PixmapPtr pBackground, RegionPtr pExpose) +{ + RegionRec expose; + miBSWindowPtr pBackingStore; + + REGION_INIT(pWin -> pScreen, &expose, NullBox, 1); + + #ifdef DEBUG + fprintf(stderr, "nxagentSendBackgroundExpose: Original expose region is [%d,%d,%d,%d].\n", + pExpose -> extents.x1, pExpose -> extents.y1, + pExpose -> extents.x2, pExpose -> extents.y2); + + fprintf(stderr, "nxagentSendBackgroundExpose: Window clipList is [%d,%d,%d,%d].\n", + pWin -> clipList.extents.x1, pWin -> clipList.extents.y1, + pWin -> clipList.extents.x2, pWin -> clipList.extents.y2); + #endif + + if (nxagentDrawableStatus((DrawablePtr) pBackground) == Synchronized && + (pBackground -> drawable.width < pWin -> drawable.width || + pBackground -> drawable.height < pWin -> drawable.height)) + { + #ifdef TEST + fprintf(stderr, "nxagentSendBackgroundExpose: Pixmap background [%dx%d] is " + "smaller than window [%dx%d]. Going to expose the winSize.\n", + pBackground -> drawable.width, pBackground -> drawable.height, + pWin -> drawable.width, pWin -> drawable.height); + #endif + + REGION_COPY(pWin -> pScreen, &expose, &pWin -> winSize); + } + else + { + REGION_COPY(pWin -> pScreen, &expose, pExpose); + + REGION_TRANSLATE(pWin -> pScreen, &expose, pWin -> drawable.x, pWin -> drawable.y); + } + + REGION_SUBTRACT(pWin -> pScreen, &expose, &expose, nxagentCorruptedRegion((DrawablePtr) pWin)); + + if (REGION_NIL(&pWin -> clipList) != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSendBackgroundExpose: Exposures deferred because the window " + "is hidden.\n"); + #endif + + REGION_UNION(pWin -> pScreen, nxagentDeferredBackgroundExposures, + nxagentDeferredBackgroundExposures, &expose); + + nxagentWindowPriv(pWin) -> deferredBackgroundExpose = 1; + + goto nxagentSendBackgroundExposeEnd; + } + + #ifdef TEST + fprintf(stderr, "nxagentSendBackgroundExpose: Sending expose [%d,%d,%d,%d].\n", + expose.extents.x1, expose.extents.y1, expose.extents.x2, expose.extents.y2); + #endif + + /* + * This prevents hidden region to be exposed. + */ + + pBackingStore = (miBSWindowPtr)pWin->backStorage; + + if ((pBackingStore != NULL) && (REGION_NIL(&pBackingStore->SavedRegion) == 0)) + { + REGION_TRANSLATE(pWin -> pScreen, &expose, -pWin -> drawable.x, -pWin -> drawable.y); + + REGION_SUBTRACT(pWin -> pScreen, &expose, &expose, &pBackingStore -> SavedRegion); + + REGION_TRANSLATE(pWin -> pScreen, &expose, pWin -> drawable.x, pWin -> drawable.y); + } + + REGION_INTERSECT(pWin -> pScreen, &expose, &expose, &pWin -> clipList); + + miWindowExposures(pWin, &expose, &expose); + +nxagentSendBackgroundExposeEnd: + + REGION_UNINIT(pWin -> pScreen, &expose); +} + +void nxagentExposeBackgroundPredicate(void *p0, XID x1, void *p2) +{ + WindowPtr pWin = (WindowPtr) p0; + WindowPtr pParent; + + struct nxagentExposeBackground *pPair = p2; + + if (REGION_NIL(pPair -> pExpose) != 0) + { + return; + } + + if (pWin -> backgroundState == BackgroundPixmap && + pWin -> background.pixmap == pPair -> pBackground) + { + #ifdef TEST + fprintf(stderr, "nxagentExposeBackgroundPredicate: Window at [%p] uses pixmap [%p] " + "as background.\n", (void *) pWin, (void *) pPair -> pBackground); + #endif + + nxagentSendBackgroundExpose(pWin, pPair -> pBackground, pPair -> pExpose); + } + else if (pWin -> backgroundState == ParentRelative) + { + #ifdef TEST + fprintf(stderr, "nxagentExposeBackgroundPredicate: Window [%p] uses parent's background.\n", + (void *) pWin); + #endif + + pParent = pWin -> parent; + + while (pParent != NULL) + { + if (pParent -> backgroundState == BackgroundPixmap && + pParent -> background.pixmap == pPair -> pBackground) + { + #ifdef TEST + fprintf(stderr, "nxagentExposeBackgroundPredicate: Parent window at [%p] uses pixmap [%p] " + "as background.\n", (void *) pParent, (void *) pPair -> pBackground); + #endif + + nxagentSendBackgroundExpose(pWin, pPair -> pBackground, pPair -> pExpose); + + break; + } + + pParent = pParent -> parent; + } + } +} + +/* + * This function is similar to nxagentClipAndSendExpose(). + */ + +int nxagentClipAndSendClearExpose(WindowPtr pWin, pointer ptr) +{ + RegionPtr exposeRgn; + RegionPtr remoteExposeRgn; + + #ifdef DEBUG + BoxRec box; + #endif + + remoteExposeRgn = (RegionRec *) ptr; + + if (nxagentWindowPriv(pWin) -> deferredBackgroundExpose == 1) + { + exposeRgn = REGION_CREATE(pWin -> drawable.pScreen, NULL, 1); + + #ifdef DEBUG + box = *REGION_EXTENTS(pWin->drawable.pScreen, remoteExposeRgn); + + fprintf(stderr, "nxagentClipAndSendClearExpose: Background expose extents: [%d,%d,%d,%d].\n", + box.x1, box.y1, box.x2, box.y2); + + box = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin -> clipList); + + fprintf(stderr, "nxagentClipAndSendClearExpose: Clip list extents for window at [%p]: [%d,%d,%d,%d].\n", + (void *) pWin, box.x1, box.y1, box.x2, box.y2); + #endif + + REGION_INTERSECT(pWin -> drawable.pScreen, exposeRgn, remoteExposeRgn, &pWin -> clipList); + + /* + * If the region will be synchronized, + * the expose on corrupted regions can + * be ignored. + */ + + REGION_SUBTRACT(pWin -> drawable.pScreen, exposeRgn, exposeRgn, nxagentCorruptedRegion((DrawablePtr) pWin)); + + if (REGION_NOTEMPTY(pWin -> drawable.pScreen, exposeRgn)) + { + #ifdef DEBUG + box = *REGION_EXTENTS(pWin->drawable.pScreen, exposeRgn); + + fprintf(stderr, "nxagentClipAndSendClearExpose: Forwarding expose [%d,%d,%d,%d] to window at [%p] pWin.\n", + box.x1, box.y1, box.x2, box.y2, (void *) pWin); + #endif + + REGION_SUBTRACT(pWin -> drawable.pScreen, remoteExposeRgn, remoteExposeRgn, exposeRgn); + + miWindowExposures(pWin, exposeRgn, exposeRgn); + } + + REGION_DESTROY(pWin -> drawable.pScreen, exposeRgn); + + nxagentWindowPriv(pWin) -> deferredBackgroundExpose = 0; + } + + if (REGION_NOTEMPTY(pWin -> drawable.pScreen, remoteExposeRgn)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendClearExpose: Region not empty. Walk children.\n"); + #endif + + + return WT_WALKCHILDREN; + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendClearExpose: Region empty. Stop walking.\n"); + #endif + + return WT_STOPWALKING; + } +} + +void nxagentSendDeferredBackgroundExposures(void) +{ + if (nxagentDeferredBackgroundExposures == NullRegion) + { + nxagentDeferredBackgroundExposures = REGION_CREATE(WindowTable[0] -> drawable.pScreen, NullBox, 1); + } + + if (REGION_NOTEMPTY(WindowTable[0] -> drawable.pScreen, nxagentDeferredBackgroundExposures) != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSendDeferredBackgroundExposures: Going to send deferred exposures to the root window.\n"); + #endif + + TraverseTree(WindowTable[0], nxagentClipAndSendClearExpose, (void *) nxagentDeferredBackgroundExposures); + + REGION_EMPTY(WindowTable[0] -> drawable.pScreen, nxagentDeferredBackgroundExposures); + } +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Drawable.h b/nx-X11/programs/Xserver/hw/nxagent/Drawable.h new file mode 100644 index 000000000..62af0685d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Drawable.h @@ -0,0 +1,221 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Drawable_H__ +#define __Drawable_H__ + +#include "resource.h" +#include "Windows.h" +#include "Pixmaps.h" + +/* + * Structures and macros used to manage the Lazy encoding. + */ + +typedef struct +{ + DrawablePtr pDrawable; + int drawableType; + int abort; + int windowBitmaps; + int pixmapBitmaps; + int backgroundBitmaps; + +} _nxagentSynchronizationRec; + +extern _nxagentSynchronizationRec nxagentSynchronization; + +enum DrawableStatus +{ + Synchronized, + NotSynchronized +}; + +enum SynchronizationPredicate +{ + Needed, + NotNeeded, + Delayed +}; + +/* + * Shall the synchronization wait for the + * drawable wakening? + */ + +#define DONT_WAIT 0 +#define DO_WAIT 1 + +/* + * How the synchronization loop can be + * interrupted? A 0 mask means that the + * loop can't be stopped. + */ + +#define EVENT_BREAK (1 << 0) +#define CONGESTION_BREAK (1 << 1) +#define BLOCKING_BREAK (1 << 2) + +#define NEVER_BREAK 0 +#define ALWAYS_BREAK (EVENT_BREAK | \ + CONGESTION_BREAK | \ + BLOCKING_BREAK) + +/* + * Minimum value of usage counter which + * a pixmap should have to be synchronized. + */ + +#define MINIMUM_PIXMAP_USAGE_COUNTER 2 + +/* + * This is the macro used to get the external XID + * from a generic pointer to a drawable. + */ + +#define nxagentDrawable(pDrawable) \ + ((pDrawable)->type == DRAWABLE_WINDOW ? \ + nxagentWindow((WindowPtr)pDrawable) : \ + nxagentPixmap((PixmapPtr)pDrawable)) + +#define nxagentVirtualDrawable(pDrawable) \ + (DrawablePtr)((pDrawable)->type == DRAWABLE_WINDOW ? \ + NULL : nxagentVirtualPixmap((PixmapPtr)pDrawable)) + +#define nxagentDrawablePicture(pDrawable) \ + ((DrawablePtr)((pDrawable)->type == DRAWABLE_WINDOW ? \ + nxagentWindowPriv((WindowPtr)pDrawable) -> pPicture : \ + nxagentPixmapPriv((PixmapPtr)pDrawable) -> pPicture)) + +#define nxagentCorruptedRegion(pDrawable) \ + ((pDrawable) -> type == DRAWABLE_PIXMAP ? \ + nxagentPixmapCorruptedRegion((PixmapPtr) pDrawable) : \ + nxagentWindowCorruptedRegion((WindowPtr) pDrawable)) + +#define nxagentDrawableStatus(pDrawable) \ + (REGION_NIL(nxagentCorruptedRegion(pDrawable)) ? \ + Synchronized : NotSynchronized) + +#define nxagentDrawableContainGlyphs(pDrawable) \ + ((pDrawable) -> type == DRAWABLE_PIXMAP ? \ + nxagentPixmapContainGlyphs((PixmapPtr) (pDrawable)) : \ + nxagentWindowContainGlyphs((WindowPtr) (pDrawable))) + +#define nxagentSetDrawableContainGlyphs(pDrawable, value) \ +do \ +{ \ + if ((pDrawable) -> type == DRAWABLE_PIXMAP) \ + { \ + nxagentPixmapContainGlyphs(nxagentRealPixmap((PixmapPtr) (pDrawable))) = (value); \ + } \ + else \ + { \ + nxagentWindowContainGlyphs((WindowPtr) (pDrawable)) = (value); \ + } \ +} while (0) + +#define nxagentDrawableBitmap(pDrawable) \ + ((pDrawable) -> type == DRAWABLE_PIXMAP ? \ + nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) (pDrawable))) -> synchronizationBitmap : \ + nxagentWindowPriv((WindowPtr) (pDrawable)) -> synchronizationBitmap) + +#define nxagentDrawableTimestamp(pDrawable) \ + ((pDrawable) -> type == DRAWABLE_PIXMAP ? \ + nxagentPixmapTimestamp((PixmapPtr) pDrawable) : \ + nxagentWindowTimestamp((WindowPtr) pDrawable)) + +#define nxagentDrawableType(pDrawable) \ + ((pDrawable) -> type == DRAWABLE_PIXMAP ? "pixmap" : "window") + +extern RESTYPE RT_NX_CORR_BACKGROUND; +extern RESTYPE RT_NX_CORR_WINDOW; +extern RESTYPE RT_NX_CORR_PIXMAP; + +extern int nxagentCorruptedPixmaps; +extern int nxagentCorruptedWindows; +extern int nxagentCorruptedBackgrounds; + +extern int nxagentForceSynchronization; + +extern RegionPtr nxagentCreateRegion(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int width, int height); + +#define nxagentFreeRegion(pDrawable, pRegion) \ + REGION_DESTROY((pDrawable) -> pScreen, pRegion); + +extern void nxagentMarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion); +extern void nxagentUnmarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion); +extern void nxagentMoveCorruptedRegion(WindowPtr pWin, unsigned int mask); +extern void nxagentIncreasePixmapUsageCounter(PixmapPtr pPixmap); + +extern int nxagentSynchronizeRegion(DrawablePtr pDrawable, RegionPtr pRegion, unsigned int breakMask, WindowPtr owner); +extern void nxagentSynchronizeBox(DrawablePtr pDrawable, BoxPtr pBox, unsigned int breakMask); +extern int nxagentSynchronizeDrawable(DrawablePtr pDrawable, int wait, unsigned int breakMask, WindowPtr owner); +extern int nxagentSynchronizeDrawableData(DrawablePtr pDrawable, unsigned int breakMask, WindowPtr owner); +extern void nxagentSynchronizationLoop(unsigned int mask); + +extern int nxagentSynchronizationPredicate(void); + +extern BoxPtr nxagentGetOptimizedRegionBoxes(RegionPtr pRegion); + +extern void nxagentCleanCorruptedDrawable(DrawablePtr pDrawable); + +extern void nxagentUnmarkExposedRegion(WindowPtr pWin, RegionPtr pRegion, RegionPtr pOther); +extern void nxagentSendDeferredBackgroundExposures(void); + +extern void nxagentClearRegion(DrawablePtr pDrawable, RegionPtr pRegion); +extern void nxagentFillRemoteRegion(DrawablePtr pDrawable, RegionPtr pRegion); + +extern void nxagentAllocateCorruptedResource(DrawablePtr pDrawable, RESTYPE type); +extern void nxagentDestroyCorruptedResource(DrawablePtr pDrawable, RESTYPE type); +extern int nxagentDestroyCorruptedBackgroundResource(pointer p, XID id); +extern int nxagentDestroyCorruptedWindowResource(pointer p, XID id); +extern int nxagentDestroyCorruptedPixmapResource(pointer p, XID id); + +extern void nxagentCreateDrawableBitmap(DrawablePtr pDrawable); +extern void nxagentDestroyDrawableBitmap(DrawablePtr pDrawable); + +extern void nxagentRegionsOnScreen(void); + +#define PRINT_REGION_BOXES(pRegion, strRegion) \ +do \ +{ \ + int i; \ + int numRects; \ + BoxPtr pBox; \ +\ + if (pRegion == NullRegion) \ + { \ + fprintf(stderr, "printRegionBoxes:: Region " strRegion " is null.\n"); \ + break; \ + } \ +\ + numRects = REGION_NUM_RECTS(pRegion); \ + pBox = REGION_RECTS(pRegion); \ +\ + fprintf(stderr, "printRegionBoxes:: Region " strRegion " at [%p] has [%d] boxes:\n", \ + (void *) (pRegion), numRects); \ +\ + for (i = 0; i < numRects; i++) \ + { \ + fprintf(stderr, "[%d] [%d,%d,%d,%d]\n", \ + i, pBox[i].x1, pBox[i].y1, pBox[i].x2, pBox[i].y2); \ + } \ +\ +} while (0) + +#endif /* __Drawable_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Error.c b/nx-X11/programs/Xserver/hw/nxagent/Error.c new file mode 100644 index 000000000..e60845dd3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Error.c @@ -0,0 +1,636 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +#include "os.h" + +#include "scrnintstr.h" +#include "Agent.h" + +#include "Xlib.h" +#include "Xproto.h" + +#include "Error.h" +#include "Args.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + + +/* + * Duplicated stderr file descriptor. + */ + +static int nxagentStderrDup = -1; + +/* + * Saved stderr file descriptor. + */ + +static int nxagentStderrBackup = -1; + +/* + * Clients log file descriptor. + */ + +static int nxagentClientsLog = -1; + +#define DEFAULT_STRING_LENGTH 256 + + +/* + * Clients log file name. + */ + +char nxagentClientsLogName[DEFAULT_STRING_LENGTH] = { 0 }; + +/* + * User's home. + */ + +static char nxagentHomeDir[DEFAULT_STRING_LENGTH] = { 0 }; + +/* + * NX root directory. + */ + +static char nxagentRootDir[DEFAULT_STRING_LENGTH] = { 0 }; + +/* + * Session log Directory. + */ + +static char nxagentSessionDir[DEFAULT_STRING_LENGTH] = { 0 }; + +char *nxagentGetClientsPath(void); + +static int nxagentPrintError(Display *dpy, XErrorEvent *event, FILE *fp); + +/* declare an error handler that does not exit when an error + * event is catched. + */ + +int nxagentErrorHandler(Display *dpy, XErrorEvent *event) +{ + if (nxagentVerbose == 1) + { + nxagentPrintError(dpy, event, stderr); + } + + return 0; +} + +/* copied from XlibInt.c */ +/* extension stuff roughly commented out */ +static int nxagentPrintError(dpy, event, fp) + Display *dpy; + XErrorEvent *event; + FILE *fp; +{ + char buffer[BUFSIZ]; + char mesg[BUFSIZ]; + char number[32]; + char *mtype = "XlibMessage"; + /* + register _XExtension *ext = (_XExtension *)NULL; + _XExtension *bext = (_XExtension *)NULL; + */ + XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); + XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); + (void) fprintf(fp, "%s: %s\n ", mesg, buffer); + XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", + mesg, BUFSIZ); + (void) fprintf(fp, mesg, event->request_code); + if (event->request_code < 128) { + sprintf(number, "%d", event->request_code); + XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); + } else { + /* for (ext = dpy->ext_procs; + ext && (ext->codes.major_opcode != event->request_code); + ext = ext->next) + ; + if (ext) + strcpy(buffer, ext->name); + else + */ + buffer[0] = '\0'; + } + (void) fprintf(fp, " (%s)\n", buffer); + if (event->request_code >= 128) { + XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->minor_code); + /* + if (ext) { + sprintf(mesg, "%s.%d", ext->name, event->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); + (void) fprintf(fp, " (%s)", buffer); + } + */ + fputs("\n", fp); + } + if (event->error_code >= 128) { + /* kludge, try to find the extension that caused it */ + buffer[0] = '\0'; + /* + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_string) + (*ext->error_string)(dpy, event->error_code, &ext->codes, + buffer, BUFSIZ); + if (buffer[0]) { + bext = ext; + break; + } + if (ext->codes.first_error && + ext->codes.first_error < (int)event->error_code && + (!bext || ext->codes.first_error > bext->codes.first_error)) + bext = ext; + } + if (bext) + sprintf(buffer, "%s.%d", bext->name, + event->error_code - bext->codes.first_error); + else + */ + strcpy(buffer, "Value"); + XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); + if (mesg[0]) { + fputs(" ", fp); + (void) fprintf(fp, mesg, event->resourceid); + fputs("\n", fp); + } + /* let extensions try to print the values */ + /* + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_values) + (*ext->error_values)(dpy, event, fp); + } + */ + } else if ((event->error_code == BadWindow) || + (event->error_code == BadPixmap) || + (event->error_code == BadCursor) || + (event->error_code == BadFont) || + (event->error_code == BadDrawable) || + (event->error_code == BadColor) || + (event->error_code == BadGC) || + (event->error_code == BadIDChoice) || + (event->error_code == BadValue) || + (event->error_code == BadAtom)) { + if (event->error_code == BadValue) + XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", + mesg, BUFSIZ); + else if (event->error_code == BadAtom) + XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", + mesg, BUFSIZ); + else + XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->resourceid); + fputs("\n", fp); + } + XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", + mesg, BUFSIZ); + fputs(" ", fp); + (void) fprintf(fp, mesg, event->serial); + XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", + mesg, BUFSIZ); + fputs("\n ", fp); + /* (void) fprintf(fp, mesg, dpy->request); */ + fputs("\n", fp); + if (event->error_code == BadImplementation) return 0; + return 1; +} + +int nxagentExitHandler(const char *message) +{ + FatalError(message); + + return 0; +} + +void nxagentOpenClientsLogFile() +{ + char * clientsLogName; + + if (*nxagentClientsLogName == '\0') + { + clientsLogName = nxagentGetClientsPath(); + + if (clientsLogName != NULL) + { + free(clientsLogName); + } + } + + if (nxagentClientsLogName != NULL && *nxagentClientsLogName !='\0') + { + nxagentClientsLog = open(nxagentClientsLogName, O_RDWR | O_CREAT | O_APPEND, 0600); + + if (nxagentClientsLog == -1) + { + fprintf(stderr, "Warning: Failed to open clients log. Error is %d '%s'.\n", + errno, strerror(errno)); + } + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentOpenClientsLogFile: Cannot open clients log file. The path does not exist.\n"); + #endif + } +} + +void nxagentCloseClientsLogFile(void) +{ + close(nxagentClientsLog); +} + +void nxagentStartRedirectToClientsLog(void) +{ + nxagentOpenClientsLogFile(); + + if (nxagentClientsLog != -1) + { + if (nxagentStderrBackup == -1) + { + nxagentStderrBackup = dup(2); + } + + if (nxagentStderrBackup != -1) + { + nxagentStderrDup = dup2(nxagentClientsLog, 2); + + if (nxagentStderrDup == -1) + { + fprintf(stderr, "Warning: Failed to redirect stderr. Error is %d '%s'.\n", + errno, strerror(errno)); + } + } + else + { + fprintf(stderr, "Warning: Failed to backup stderr. Error is %d '%s'.\n", + errno, strerror(errno)); + } + } +} + +void nxagentEndRedirectToClientsLog(void) +{ + if (nxagentStderrBackup != -1) + { + nxagentStderrDup = dup2(nxagentStderrBackup, 2); + + if (nxagentStderrDup == -1) + { + fprintf(stderr, "Warning: Failed to restore stderr. Error is %d '%s'.\n", + errno, strerror(errno)); + } + } + + nxagentCloseClientsLogFile(); +} + +char *nxagentGetHomePath(void) +{ + char *homeEnv; + char *homePath; + + if (*nxagentHomeDir == '\0') + { + /* + * Check the NX_HOME environment. + */ + + homeEnv = getenv("NX_HOME"); + + if (homeEnv == NULL || *homeEnv == '\0') + { + #ifdef TEST + fprintf(stderr, "nxagentGetHomePath: No environment for NX_HOME.\n"); + #endif + + homeEnv = getenv("HOME"); + + if (homeEnv == NULL || *homeEnv == '\0') + { + #ifdef PANIC + fprintf(stderr, "nxagentGetHomePath: PANIC! No environment for HOME.\n"); + #endif + + return NULL; + } + } + + if (strlen(homeEnv) > DEFAULT_STRING_LENGTH - 1) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetHomePath: PANIC! Invalid value for the NX " + "home directory '%s'.\n", homeEnv); + #endif + } + + strncpy(nxagentHomeDir, homeEnv, DEFAULT_STRING_LENGTH - 1); + + #ifdef TEST + fprintf(stderr, "nxagentGetHomePath: Assuming NX user's home directory '%s'.\n", nxagentHomeDir); + #endif + } + + homePath = (char*) malloc(strlen(nxagentHomeDir) + 1); + + if (homePath == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetHomePath: PANIC! Can't allocate memory for the home path.\n"); + #endif + + return NULL; + } + + strcpy(homePath, nxagentHomeDir); + + return homePath; +} + +char *nxagentGetRootPath(void) +{ + char *rootEnv; + char *homeEnv; + char *rootPath; + + struct stat dirStat; + + if (*nxagentRootDir == '\0') + { + /* + * Check the NX_ROOT environment. + */ + + rootEnv = getenv("NX_ROOT"); + + if (rootEnv == NULL || *rootEnv == '\0') + { + #ifdef TEST + fprintf(stderr, "nxagentGetRootPath: WARNING! No environment for NX_ROOT.\n"); + #endif + + /* + * We will determine the root NX directory + * based on the NX_HOME or HOME directory + * settings. + */ + + homeEnv = nxagentGetHomePath(); + + if (homeEnv == NULL) + { + + #ifdef PANIC + #endif + + return NULL; + } + + if (strlen(homeEnv) > DEFAULT_STRING_LENGTH - + strlen("/.nx") - 1) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetRootPath: PANIC! Invalid value for the NX " + "home directory '%s'.\n", homeEnv); + #endif + + free(homeEnv); + + return NULL; + } + + #ifdef TEST + fprintf(stderr, "nxagentGetRootPath: Assuming NX root directory in '%s'.\n", homeEnv); + #endif + + strcpy(nxagentRootDir, homeEnv); + strcat(nxagentRootDir, "/.nx"); + + free(homeEnv); + + /* + * Create the NX root directory. + */ + + if ((stat(nxagentRootDir, &dirStat) == -1) && (errno == ENOENT)) + { + if (mkdir(nxagentRootDir, 0777) < 0 && (errno != EEXIST)) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetRootPath: PANIC! Can't create directory '%s'. Error is %d '%s'.\n", + nxagentRootDir, errno, strerror(errno)); + #endif + + return NULL; + } + } + } + else + { + if (strlen(rootEnv) > DEFAULT_STRING_LENGTH - 1) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetRootPath: PANIC! Invalid value for the NX root directory '%s'.\n", + rootEnv); + #endif + + return NULL; + } + + strcpy(nxagentRootDir, rootEnv); + } + + #ifdef TEST + fprintf(stderr, "nxagentGetRootPath: Assuming NX root directory '%s'.\n", + nxagentRootDir); + #endif + + } + + rootPath = malloc(strlen(nxagentRootDir) + 1); + + if (rootPath == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetRootPath: Can't allocate memory for the root path.\n"); + #endif + + return NULL; + } + + strcpy(rootPath, nxagentRootDir); + + return rootPath; +} + +char *nxagentGetSessionPath() +{ + + char *rootPath; + char *sessionPath; + + struct stat dirStat; + + if (*nxagentSessionDir == '\0') + { + /* + * If nxagentSessionId does not exist we + * assume that the sessionPath cannot be + * realized and do not use the clients + * log file. + */ + + if (*nxagentSessionId == '\0') + { + #ifdef TEST + fprintf(stderr, "nxagentGetSessionPath: Session id does not exist. Assuming session path NULL.\n"); + #endif + + return NULL; + } + + rootPath = nxagentGetRootPath(); + + if (rootPath == NULL) + { + return NULL; + } + + strcpy(nxagentSessionDir, rootPath); + + free(rootPath); + + if (strlen(nxagentSessionDir) + strlen("/C-") + strlen(nxagentSessionId) > DEFAULT_STRING_LENGTH - 1) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetSessionPath: PANIC!: Invalid value for the NX session directory '%s'.\n", + nxagentSessionDir); + #endif + + return NULL; + } + + strcat(nxagentSessionDir, "/C-"); + + strcat(nxagentSessionDir, nxagentSessionId); + + if ((stat(nxagentSessionDir, &dirStat) == -1) && (errno == ENOENT)) + { + if (mkdir(nxagentSessionDir, 0777) < 0 && (errno != EEXIST)) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetSessionPath: PANIC! Can't create directory '%s'. Error is %d '%s'.\n", + nxagentSessionDir, errno, strerror(errno)); + #endif + + return NULL; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentGetSessionPath: NX session is '%s'.\n", + nxagentSessionDir); + #endif + + } + + sessionPath = malloc(strlen(nxagentSessionDir) + 1); + + if (sessionPath == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetSessionPath:: PANIC! Can't allocate memory for the session path.\n"); + #endif + + return NULL; + } + + + strcpy(sessionPath, nxagentSessionDir); + + return sessionPath; +} + +char *nxagentGetClientsPath() +{ + char *sessionPath; + char *clientsPath; + + if (*nxagentClientsLogName == '\0') + { + sessionPath = nxagentGetSessionPath(); + + if (sessionPath == NULL) + { + return NULL; + } + + if (strlen(sessionPath) + strlen("/clients") > DEFAULT_STRING_LENGTH - 1) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetClientsPath: PANIC! Invalid value for the NX clients Log File Path '%s'.\n", + nxagentClientsLogName); + #endif + + free(sessionPath); + + return NULL; + } + + strcpy(nxagentClientsLogName, sessionPath); + + strcat(nxagentClientsLogName, "/clients"); + + free(sessionPath); + } + + clientsPath = malloc(strlen(nxagentClientsLogName) + 1); + + if (clientsPath == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentGetClientsPath: PANIC! Can't allocate memory for the clients Log File Path path.\n"); + #endif + + return NULL; + } + + strcpy(clientsPath, nxagentClientsLogName); + + return clientsPath; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Error.h b/nx-X11/programs/Xserver/hw/nxagent/Error.h new file mode 100644 index 000000000..78e15592b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Error.h @@ -0,0 +1,37 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Error_H__ +#define __Error_H__ + +/* + * Clients log file name. + */ + +extern char nxagentClientsLogName[]; + +extern char nxagentVerbose; + +int nxagentErrorHandler(Display *dpy, XErrorEvent *event); + +int nxagentExitHandler(const char *message); + +void nxagentStartRedirectToClientsLog(void); + +void nxagentEndRedirectToClientsLog(void); + +#endif /* __Error_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c new file mode 100644 index 000000000..e1eab6fd2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c @@ -0,0 +1,3822 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "X.h" +#include "signal.h" +#include "unistd.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "selection.h" +#include "keysym.h" +#include "fb.h" +#include "mibstorest.h" +#include "osdep.h" + +#include "Agent.h" +#include "Args.h" +#include "Atoms.h" +#include "Colormap.h" +#include "Display.h" +#include "Screen.h" +#include "Windows.h" +#include "Pixmaps.h" +#include "Keyboard.h" +#include "Keystroke.h" +#include "Events.h" +#include "Pointer.h" +#include "Rootless.h" +#include "Splash.h" +#include "Trap.h" +#include "Dialog.h" +#include "Client.h" +#include "Clipboard.h" +#include "Split.h" +#include "Drawable.h" +#include "Handlers.h" +#include "Utils.h" + +#include "NX.h" +#include "NXvars.h" +#include "NXproto.h" + +#ifdef NXAGENT_FIXKEYS +#include "inputstr.h" +#include "input.h" +#endif + +#include "XKBlib.h" + +#define GC XlibGC +#define Font XlibFont +#define KeySym XlibKeySym +#define XID XlibXID +#include "Xlibint.h" +#undef GC +#undef Font +#undef KeySym +#undef XID + +#include + +#include "Shadow.h" +#include "Xrandr.h" + +#include "NXlib.h" + +/* + * Set here the required log level. Please note + * that if you want to enable DEBUG here, then + * you need to enable DEBUG even in Rootless.c + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Log begin and end of the important handlers. + */ + +#undef BLOCKS + +extern Bool nxagentOnce; + +extern WindowPtr nxagentRootTileWindow; +extern int nxagentSplashCount; + +extern int nxagentLastClipboardClient; + +#ifdef DEBUG +extern Bool nxagentRootlessTreesMatch(void); +#endif + +Bool xkbdRunning = False; +pid_t pidkbd; + +WindowPtr nxagentLastEnteredWindow = NULL; + +PropertyRequestRec nxagentPropertyRequests[NXNumberOfResources]; + +void nxagentHandleCollectPropertyEvent(XEvent*); + +/* + * Finalize the asynchronous handling + * of the X_GrabPointer requests. + */ + +void nxagentHandleCollectGrabPointerEvent(int resource); + +Bool nxagentCollectGrabPointerPredicate(Display *display, XEvent *X, XPointer ptr); + +/* + * Used in Handlers.c to synchronize + * the agent with the remote X server. + */ + +void nxagentHandleCollectInputFocusEvent(int resource); + +/* + * Viewport navigation. + */ + +static int viewportInc = 1; +static enum HandleEventResult viewportLastKeyPressResult; +static int viewportLastX; +static int viewportLastY; +static Cursor viewportCursor; + +/* + * Keyboard and pointer are handled as they were real devices by + * Xnest and we inherit this behaviour. The following mask will + * contain the event mask selected for the root window of the + * agent. All the keyboard and pointer events will be translated + * by the agent and sent to the internal clients according to + * events selected by the inferior windows. + */ + +static Mask defaultEventMask; + +#define MAX_INC 200 +#define INC_STEP 5 +#define nextinc(x) ((x) < MAX_INC ? (x) += INC_STEP : (x)) + +/* + * Used to mask the appropriate bits in + * the state reported by XkbStateNotify + * and XkbGetIndicatorState. + */ + +#define CAPSFLAG_IN_REPLY 1 +#define CAPSFLAG_IN_EVENT 2 +#define NUMFLAG_IN_EVENT 16 +#define NUMFLAG_IN_REPLY 2 + +CARD32 nxagentLastEventTime = 0; +CARD32 nxagentLastKeyPressTime = 0; +Time nxagentLastServerTime = 0; + +/* + * Used for storing windows that need to + * receive expose events from the agent. + */ + +#define nxagentExposeQueueHead nxagentExposeQueue.exposures[nxagentExposeQueue.start] + +ExposeQueue nxagentExposeQueue; + +RegionPtr nxagentRemoteExposeRegion = NULL; + +static void nxagentForwardRemoteExpose(void); + +static int nxagentClipAndSendExpose(WindowPtr pWin, pointer ptr); + +/* + * Associate a resource to a drawable and + * store the region affected by the split + * operation. + */ + +SplitResourceRec nxagentSplitResources[NXNumberOfResources]; + +/* + * Associate a resource to an unpack + * operation. + */ + +UnpackResourceRec nxagentUnpackResources[NXNumberOfResources]; + +/* + * We have to check these before launching + * the terminate dialog in rootless mode. + */ + +Bool nxagentLastWindowDestroyed = False; +Time nxagentLastWindowDestroyedTime = 0; + +/* + * Set this flag when an user input event + * is received. + */ + +int nxagentInputEvent = 0; + +int nxagentKeyDown = 0; + +void nxagentSwitchResizeMode(ScreenPtr pScreen); + +int nxagentCheckWindowConfiguration(XConfigureEvent* X); + +#define nxagentMonitoredDuplicate(keysym) \ + ((keysym) == XK_Left || (keysym) == XK_Up || \ + (keysym) == XK_Right || (keysym) == XK_Down || \ + (keysym) == XK_Page_Up || (keysym) == XK_Page_Down || \ + (keysym) == XK_Delete || (keysym) == XK_BackSpace) + +void nxagentRemoveDuplicatedKeys(XEvent *X); + +void ProcessInputEvents() +{ + mieqProcessInputEvents(); +} + +void nxagentSwitchResizeMode(ScreenPtr pScreen) +{ + XSizeHints sizeHints; + + int desktopResize = nxagentOption(DesktopResize); + + nxagentChangeOption(DesktopResize, !desktopResize); + + sizeHints.flags = PMaxSize; + + if (nxagentOption(DesktopResize) == 0) + { + fprintf(stderr,"Info: Disabled desktop resize mode in agent.\n"); + + nxagentLaunchDialog(DIALOG_DISABLE_DESKTOP_RESIZE_MODE); + + sizeHints.max_width = nxagentOption(RootWidth); + sizeHints.max_height = nxagentOption(RootHeight); + } + else + { + fprintf(stderr,"Info: Enabled desktop resize mode in agent.\n"); + + nxagentLaunchDialog(DIALOG_ENABLE_DESKTOP_RESIZE_MODE); + + nxagentRRSetScreenConfig(pScreen, nxagentOption(Width), nxagentOption(Height)); + + sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + } + + XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + &sizeHints); +} + +void nxagentShadowSwitchResizeMode(ScreenPtr pScreen) +{ + XSizeHints sizeHints; + + int desktopResize = nxagentOption(DesktopResize); + + nxagentChangeOption(DesktopResize, !desktopResize); + + sizeHints.flags = PMaxSize; + + if (nxagentOption(DesktopResize) == 0) + { + nxagentShadowSetRatio(1.0, 1.0); + + nxagentShadowCreateMainWindow(screenInfo.screens[DefaultScreen(nxagentDisplay)], WindowTable[0], + WindowTable[0] -> drawable.width, WindowTable[0] -> drawable.height); + + sizeHints.max_width = nxagentOption(RootWidth); + sizeHints.max_height = nxagentOption(RootHeight); + + fprintf(stderr,"Info: Disabled resize mode in shadow agent.\n"); + } + else + { + nxagentShadowSetRatio(nxagentOption(Width) * 1.0 / + WindowTable[0] -> drawable.width, + nxagentOption(Height) * 1.0 / + WindowTable[0] -> drawable.height); + + nxagentShadowCreateMainWindow(screenInfo.screens[DefaultScreen(nxagentDisplay)], + WindowTable[0], WindowTable[0] -> drawable.width, + WindowTable[0] -> drawable.height); + + sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + + fprintf(stderr,"Info: Enabled resize mode in shadow agent.\n"); + } + + XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + &sizeHints); +} + +static void nxagentSwitchDeferMode(void) +{ + if (nxagentOption(DeferLevel) == 0) + { + nxagentChangeOption(DeferLevel, UNDEFINED); + + nxagentSetDeferLevel(); + } + else + { + nxagentChangeOption(DeferLevel, 0); + } + + if (nxagentOption(DeferLevel) != 0) + { + nxagentLaunchDialog(DIALOG_ENABLE_DEFER_MODE); + } + else + { + nxagentLaunchDialog(DIALOG_DISABLE_DEFER_MODE); + + nxagentForceSynchronization = 1; + } +} + +static Bool nxagentExposurePredicate(Display *display, XEvent *event, XPointer window) +{ + /* + * Handle both Expose and ProcessedExpose events. + * The latters are those not filtered by function + * nxagentWindowExposures(). + */ + + if (window) + { + return ((event -> type == Expose || event -> type == ProcessedExpose) && + event -> xexpose.window == *((Window *) window)); + } + else + { + return (event -> type == Expose || event -> type == ProcessedExpose); + } +} + +static int nxagentAnyEventPredicate(Display *display, XEvent *event, XPointer parameter) +{ + return 1; +} + +int nxagentInputEventPredicate(Display *display, XEvent *event, XPointer parameter) +{ + switch (event -> type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + { + return 1; + } + default: + { + return 0; + } + } +} + +void nxagentInitDefaultEventMask() +{ + Mask mask = NoEventMask; + + mask |= (StructureNotifyMask | VisibilityChangeMask); + + mask |= ExposureMask; + + mask |= NXAGENT_KEYBOARD_EVENT_MASK; + mask |= NXAGENT_POINTER_EVENT_MASK; + + defaultEventMask = mask; +} + +void nxagentGetDefaultEventMask(Mask *mask_return) +{ + *mask_return = defaultEventMask; +} + +void nxagentSetDefaultEventMask(Mask mask) +{ + defaultEventMask = mask; +} + +void nxagentGetEventMask(WindowPtr pWin, Mask *mask_return) +{ + Mask mask = NoEventMask; + + if (nxagentOption(Rootless)) + { + /* + * mask = pWin -> eventMask & + * ~(NXAGENT_KEYBOARD_EVENT_MASK | NXAGENT_POINTER_EVENT_MASK); + */ + + if (pWin -> drawable.class == InputOutput) + { + if (nxagentWindowTopLevel(pWin)) + { + mask = defaultEventMask; + } + else + { + mask = ExposureMask | VisibilityChangeMask | PointerMotionMask; + } + } + + mask |= PropertyChangeMask; + } + else if (pWin -> drawable.class != InputOnly) + { + mask = ExposureMask | VisibilityChangeMask; + } + + *mask_return = mask; +} + +static int nxagentChangeMapPrivate(WindowPtr pWin, pointer ptr) +{ + if (pWin && nxagentWindowPriv(pWin)) + { + nxagentWindowPriv(pWin) -> isMapped = *((Bool *) ptr); + } + + return WT_WALKCHILDREN; +} + +static int nxagentChangeVisibilityPrivate(WindowPtr pWin, pointer ptr) +{ + if (pWin && nxagentWindowPriv(pWin)) + { + nxagentWindowPriv(pWin) -> visibilityState = *((int *) ptr); + } + + return WT_WALKCHILDREN; +} + +void nxagentDispatchEvents(PredicateFuncPtr predicate) +{ + XEvent X; + xEvent x; + ScreenPtr pScreen = NULL; + + Bool minimize = False; + Bool startKbd = False; + Bool closeSession = False; + Bool switchFullscreen = False; + + /* + * Last entered top level window. + */ + + static WindowPtr nxagentLastEnteredTopLevelWindow = NULL; + + #ifdef BLOCKS + fprintf(stderr, "[Begin read]\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new events with " + "predicate [%p].\n", predicate); + #endif + + if (nxagentRemoteExposeRegion == NULL) + { + nxagentInitRemoteExposeRegion(); + } + + /* + * We must read here, even if apparently there is + * nothing to read. The ioctl() based readable + * function, in fact, is often unable to detect a + * failure of the socket, in particular if the + * agent was connected to the proxy and the proxy + * is gone. Thus we must trust the wakeup handler + * that called us after the select(). + */ + + #ifdef TEST + + if (nxagentPendingEvents(nxagentDisplay) == 0) + { + fprintf(stderr, "nxagentDispatchEvents: PANIC! No event needs to be dispatched.\n"); + } + + #endif + + /* + * We want to process all the events already in + * the queue, plus any additional event that may + * be read from the network. If no event can be + * read, we want to continue handling our clients + * without flushing the output buffer. + */ + + while (nxagentCheckEvents(nxagentDisplay, &X, predicate != NULL ? predicate : + nxagentAnyEventPredicate, NULL) == 1) + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: Going to handle new event type [%d].\n", + X.type); + #endif + + /* + * Handle the incoming event. + */ + + switch (X.type) + { + #ifdef NXAGENT_CLIPBOARD + + case SelectionClear: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new SelectionClear event.\n"); + #endif + + nxagentClearSelection(&X); + + break; + } + case SelectionRequest: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new SelectionRequest event.\n"); + #endif + + nxagentRequestSelection(&X); + + break; + } + case SelectionNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new SelectionNotify event.\n"); + #endif + + nxagentNotifySelection(&X); + + break; + } + + #endif /* NXAGENT_CLIPBOARD */ + + case PropertyNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: PropertyNotify on " + "prop %d[%s] window %lx state %d\n", + (int)X.xproperty.atom, validateString(XGetAtomName(nxagentDisplay, X.xproperty.atom)), + X.xproperty.window, X.xproperty.state); + #endif + + nxagentHandlePropertyNotify(&X); + + break; + } + case KeyPress: + { + enum HandleEventResult result; + + KeySym keysym; + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new KeyPress event.\n"); + #endif + + nxagentInputEvent = 1; + + nxagentKeyDown++; + + nxagentHandleKeyPress(&X, &result); + + if (viewportLastKeyPressResult != result) + { + viewportInc = 1; + + viewportLastKeyPressResult = result; + } + + if (result != doNothing && result != doStartKbd) + { + pScreen = nxagentScreen(X.xkey.window); + } + + switch (result) + { + case doNothing: + { + break; + } + case doCloseSession: + { + closeSession = TRUE; + + break; + } + case doMinimize: + { + minimize = TRUE; + + break; + } + case doStartKbd: + { + startKbd = TRUE; + + break; + } + case doSwitchFullscreen: + { + switchFullscreen = TRUE; + + break; + } + case doViewportUp: + { + nxagentMoveViewport(pScreen, 0, -nextinc(viewportInc)); + + break; + } + case doViewportDown: + { + nxagentMoveViewport(pScreen, 0, +nextinc(viewportInc)); + + break; + } + case doViewportLeft: + { + nxagentMoveViewport(pScreen, -nextinc(viewportInc), 0); + + break; + } + case doViewportRight: + { + nxagentMoveViewport(pScreen, +nextinc(viewportInc), 0); + + break; + } + case doSwitchResizeMode: + { + if (nxagentOption(Shadow) == 0) + { + if (nxagentNoDialogIsRunning) + { + nxagentSwitchResizeMode(pScreen); + } + } + else + { + nxagentShadowSwitchResizeMode(pScreen); + } + + break; + } + case doSwitchDeferMode: + { + if (nxagentNoDialogIsRunning) + { + nxagentSwitchDeferMode(); + } + + break; + } + default: + { + FatalError("nxagentDispatchEvent: handleKeyPress returned unknown value\n"); + + break; + } + } + + /* + * Elide multiple KeyPress/KeyRelease events of + * the same key and generate a single pair. This + * is intended to reduce the impact of the laten- + * cy on the key auto-repeat, handled by the re- + * mote X server. We may optionally do that only + * if the timestamps in the events show an exces- + * sive delay. + */ + + keysym = XKeycodeToKeysym(nxagentDisplay, X.xkey.keycode, 0); + + if (nxagentMonitoredDuplicate(keysym) == 1) + { + nxagentRemoveDuplicatedKeys(&X); + } + + if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow) == 1 && result == doNothing) + { + NXShadowEvent(nxagentDisplay, X); + } + + break; + } + case KeyRelease: + { + enum HandleEventResult result; + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new KeyRelease event.\n"); + #endif + + nxagentInputEvent = 1; + + nxagentKeyDown--; + + if (nxagentKeyDown <= 0) + { + nxagentKeyDown = 0; + } + + if (nxagentXkbState.Initialized == 0) + { + nxagentInitKeyboardState(); + } + + x.u.u.type = KeyRelease; + x.u.u.detail = X.xkey.keycode; + x.u.keyButtonPointer.time = nxagentLastKeyPressTime + (X.xkey.time - nxagentLastServerTime); + + nxagentLastServerTime = X.xkey.time; + + nxagentLastEventTime = GetTimeInMillis(); + + if (!(nxagentCheckSpecialKeystroke(&X.xkey, &result))) + { + mieqEnqueue(&x); + + CriticalOutputPending = 1; + + if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow)) + { + NXShadowEvent(nxagentDisplay, X); + } + } + + break; + } + case ButtonPress: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new ButtonPress event.\n"); + #endif + + nxagentInputEvent = 1; + + if (nxagentOption(Fullscreen)) + { + if (nxagentMagicPixelZone(X.xbutton.x, X.xbutton.y)) + { + pScreen = nxagentScreen(X.xbutton.window); + + minimize = True; + + break; + } + } + + if (nxagentIpaq && nxagentClients <= 0) + { + closeSession = TRUE; + } + + if (nxagentOption(DesktopResize) == False && + (X.xbutton.state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask)) + { + /* + * Start viewport navigation mode. + */ + + int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, + nxagentCollectGrabPointerPredicate); + + ScreenPtr pScreen = nxagentScreen(X.xbutton.window); + viewportCursor = XCreateFontCursor(nxagentDisplay, XC_fleur); + + NXCollectGrabPointer(nxagentDisplay, resource, + nxagentDefaultWindows[pScreen -> myNum], True, + NXAGENT_POINTER_EVENT_MASK, GrabModeAsync, + GrabModeAsync, None, viewportCursor, + CurrentTime); + viewportLastX = X.xbutton.x; + viewportLastY = X.xbutton.y; + + break; + } + + if (!(nxagentOption(Fullscreen) && + X.xbutton.window == nxagentFullscreenWindow && + X.xbutton.subwindow == None)) + { + x.u.u.type = ButtonPress; + x.u.u.detail = X.xbutton.button; + x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis(); + + if (nxagentOption(Rootless)) + { + x.u.keyButtonPointer.rootX = X.xmotion.x_root; + x.u.keyButtonPointer.rootY = X.xmotion.y_root; + } + else + { + x.u.keyButtonPointer.rootX = X.xmotion.x - nxagentOption(RootX); + x.u.keyButtonPointer.rootY = X.xmotion.y - nxagentOption(RootY); + } + + mieqEnqueue(&x); + + CriticalOutputPending = 1; + } + + if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow)) + { + X.xbutton.x -= nxagentOption(RootX); + X.xbutton.y -= nxagentOption(RootY); + + if (nxagentOption(YRatio) != DONT_SCALE) + { + X.xbutton.x = (X.xbutton.x << PRECISION) / nxagentOption(YRatio); + } + + if (nxagentOption(XRatio) != DONT_SCALE) + { + X.xbutton.y = (X.xbutton.y << PRECISION) / nxagentOption(YRatio); + } + + NXShadowEvent(nxagentDisplay, X); + } + + break; + } + case ButtonRelease: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new ButtonRelease event.\n"); + #endif + + nxagentInputEvent = 1; + + if (viewportCursor) + { + /* + * Leave viewport navigation mode. + */ + + XUngrabPointer(nxagentDisplay, CurrentTime); + + XFreeCursor(nxagentDisplay, viewportCursor); + + viewportCursor = None; + } + + if (minimize != True) + { + x.u.u.type = ButtonRelease; + x.u.u.detail = X.xbutton.button; + x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis(); + + if (nxagentOption(Rootless)) + { + x.u.keyButtonPointer.rootX = X.xmotion.x_root; + x.u.keyButtonPointer.rootY = X.xmotion.y_root; + } + else + { + x.u.keyButtonPointer.rootX = X.xmotion.x - nxagentOption(RootX); + x.u.keyButtonPointer.rootY = X.xmotion.y - nxagentOption(RootY); + } + + mieqEnqueue(&x); + + CriticalOutputPending = 1; + } + + if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow)) + { + X.xbutton.x -= nxagentOption(RootX); + X.xbutton.y -= nxagentOption(RootY); + + if (nxagentOption(XRatio) != DONT_SCALE) + { + X.xbutton.x = (X.xbutton.x << PRECISION) / nxagentOption(XRatio); + } + + if (nxagentOption(YRatio) != DONT_SCALE) + { + X.xbutton.y = (X.xbutton.y << PRECISION) / nxagentOption(YRatio); + } + + NXShadowEvent(nxagentDisplay, X); + } + + break; + } + case MotionNotify: + { + ScreenPtr pScreen = nxagentScreen(X.xmotion.window); + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new MotionNotify event.\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Handling motion notify window [%ld] root [%ld] child [%ld].\n", + X.xmotion.window, X.xmotion.root, X.xmotion.subwindow); + + fprintf(stderr, "nxagentDispatchEvents: Pointer at [%d][%d] relative root [%d][%d].\n", + X.xmotion.x, X.xmotion.y, X.xmotion.x_root, X.xmotion.y_root); + #endif + + x.u.u.type = MotionNotify; + + if (nxagentOption(Rootless)) + { + WindowPtr pWin = nxagentWindowPtr(X.xmotion.window); + + if (pWin) + { + nxagentLastEnteredWindow = pWin; + } + + if (nxagentPulldownDialogPid == 0 && (X.xmotion.y_root < + nxagentLastEnteredTopLevelWindow -> drawable.y + 4)) + { + if (pWin && nxagentLastEnteredTopLevelWindow && + nxagentClientIsDialog(wClient(pWin)) == 0 && + nxagentLastEnteredTopLevelWindow -> parent == WindowTable[0] && + nxagentLastEnteredTopLevelWindow -> overrideRedirect == False && + X.xmotion.x_root > (nxagentLastEnteredTopLevelWindow -> drawable.x + + (nxagentLastEnteredTopLevelWindow -> drawable.width >> 1) - 50) && + X.xmotion.x_root < (nxagentLastEnteredTopLevelWindow -> drawable.x + + (nxagentLastEnteredTopLevelWindow -> drawable.width >> 1) + 50) && + nxagentOption(Menu) == 1) + { + nxagentPulldownDialog(nxagentLastEnteredTopLevelWindow -> drawable.id); + } + } + + x.u.keyButtonPointer.rootX = X.xmotion.x_root; + x.u.keyButtonPointer.rootY = X.xmotion.y_root; + } + else + { + x.u.keyButtonPointer.rootX = X.xmotion.x - nxagentOption(RootX); + x.u.keyButtonPointer.rootY = X.xmotion.y - nxagentOption(RootY); + } + + x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis(); + + if (viewportCursor == None && + !(nxagentOption(Fullscreen) && + X.xmotion.window == nxagentDefaultWindows[pScreen -> myNum] + && X.xmotion.subwindow == None)) + { + mieqEnqueue(&x); + } + + /* + * This test is more complicated and probably not necessary, compared + * to a simple check on viewportCursor. + * + * if (!nxagentOption(Fullscreen) && + * (X.xmotion.state & (ControlMask | Mod1Mask | Button1Mask)) == + * (ControlMask | Mod1Mask | Button1Mask)) + */ + + if (viewportCursor) + { + /* + * Pointer is in viewport navigation mode. + */ + + nxagentMoveViewport(pScreen, viewportLastX - X.xmotion.x, viewportLastY - X.xmotion.y); + + viewportLastX = X.xmotion.x; + viewportLastY = X.xmotion.y; + } + + if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow) && !viewportCursor) + { + X.xmotion.x -= nxagentOption(RootX); + X.xmotion.y -= nxagentOption(RootY); + + if (nxagentOption(XRatio) != DONT_SCALE) + { + X.xmotion.x = (X.xmotion.x << PRECISION) / nxagentOption(XRatio); + } + + if (nxagentOption(YRatio) != DONT_SCALE) + { + X.xmotion.y = (X.xmotion.y << PRECISION) / nxagentOption(YRatio); + } + + NXShadowEvent(nxagentDisplay, X); + } + + if (nxagentOption(Shadow) == 0) + { + nxagentInputEvent = 1; + } + + break; + } + case FocusIn: + { + WindowPtr pWin; + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new FocusIn event.\n"); + #endif + + /* + * Here we change the focus state in the agent. + * It looks like this is needed only for root- + * less mode at the present moment. + */ + + if (nxagentOption(Rootless) && + (pWin = nxagentWindowPtr(X.xfocus.window))) + { + SetInputFocus(serverClient, inputInfo.keyboard, pWin -> drawable.id, + RevertToPointerRoot, GetTimeInMillis(), False); + } + + if (X.xfocus.detail != NotifyInferior) + { + pScreen = nxagentScreen(X.xfocus.window); + + if (pScreen) + { + nxagentDirectInstallColormaps(pScreen); + } + } + + break; + } + case FocusOut: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new FocusOut event.\n"); + #endif + + if (X.xfocus.detail != NotifyInferior) + { + pScreen = nxagentScreen(X.xfocus.window); + + if (pScreen) + { + nxagentDirectUninstallColormaps(pScreen); + } + } + + #ifdef NXAGENT_FIXKEYS + + { + /* + * Force the keys all up when focus is lost. + */ + + int i, k; + int mask = 1; + CARD8 val; + + XEvent xM; + memset(&xM, 0, sizeof(XEvent)); + + for (i = 0; i < DOWN_LENGTH; i++) /* input.h */ + { + val = inputInfo.keyboard->key->down[i]; + + if (val != 0) + { + for (k = 0; k < 8; k++) + { + if (val & (mask << k)) + { + #ifdef NXAGENT_FIXKEYS_DEBUG + fprintf(stderr, "sending KeyRelease event for keycode: %x\n", + i * 8 + k); + #endif + + if (!nxagentOption(Rootless) || + inputInfo.keyboard->key->modifierMap[i * 8 + k]) + { + x.u.u.type = KeyRelease; + x.u.u.detail = i * 8 + k; + x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis(); + + if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow)) + { + xM.type = KeyRelease; + xM.xkey.display = nxagentDisplay; + xM.xkey.type = KeyRelease; + xM.xkey.keycode = i * 8 + k; + xM.xkey.state = inputInfo.keyboard->key->state; + xM.xkey.time = GetTimeInMillis(); + NXShadowEvent(nxagentDisplay, xM); + } + + mieqEnqueue(&x); + } + } + } + } + } + + nxagentKeyDown = 0; + } + + #endif /* NXAGENT_FIXKEYS */ + + break; + } + case KeymapNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new KeymapNotify event.\n"); + #endif + + break; + } + case EnterNotify: + { + WindowPtr pWin; + + WindowPtr pTLWin = NULL; + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new EnterNotify event.\n"); + #endif + + if (nxagentOption(Rootless)) + { + pWin = nxagentWindowPtr(X.xcrossing.window); + + if (pWin != NULL) + { + for (pTLWin = pWin; + pTLWin -> parent != WindowTable[pTLWin -> drawable.pScreen -> myNum]; + pTLWin = pTLWin -> parent); + } + + if (pTLWin) + { + nxagentLastEnteredTopLevelWindow = pTLWin; + } + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: nxagentLastEnteredTopLevelWindow [%p].\n", + nxagentLastEnteredTopLevelWindow); + #endif + } + + if (nxagentOption(Rootless) && nxagentWMIsRunning && + (pWin = nxagentWindowPtr(X.xcrossing.window)) && + nxagentWindowTopLevel(pWin) && !pWin -> overrideRedirect && + (pWin -> drawable.x != X.xcrossing.x_root - X.xcrossing.x - pWin -> borderWidth || + pWin -> drawable.y != X.xcrossing.y_root - X.xcrossing.y - pWin -> borderWidth)) + { + /* + * This code is useful for finding the window + * position. It should be re-implemented by + * following the ICCCM 4.1.5 recommendations. + */ + + XID values[4]; + register XID *value = values; + Mask mask = 0; + ClientPtr pClient = wClient(pWin); + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: pWin -> drawable.x [%d] pWin -> drawable.y [%d].\n", + pWin -> drawable.x, pWin -> drawable.y); + #endif + + *value++ = (XID) (X.xcrossing.x_root - X.xcrossing.x - pWin -> borderWidth); + *value++ = (XID) (X.xcrossing.y_root - X.xcrossing.y - pWin -> borderWidth); + + /* + * nxagentWindowPriv(pWin)->x = (X.xcrossing.x_root - X.xcrossing.x); + * nxagentWindowPriv(pWin)->y = (X.xcrossing.y_root - X.xcrossing.y); + */ + + mask = CWX | CWY; + + nxagentScreenTrap = 1; + + ConfigureWindow(pWin, mask, (XID *) values, pClient); + + nxagentScreenTrap = 0; + } + + if (nxagentOption(Fullscreen)) + { + if (X.xcrossing.window == nxagentFullscreenWindow && + X.xcrossing.detail != NotifyInferior) + { + nxagentGrabPointerAndKeyboard(&X); + } + } + + if (X.xcrossing.detail != NotifyInferior) + { + pScreen = nxagentScreen(X.xcrossing.window); + + if (pScreen) + { + NewCurrentScreen(pScreen, X.xcrossing.x, X.xcrossing.y); + + x.u.u.type = MotionNotify; + + if (nxagentOption(Rootless)) + { + nxagentLastEnteredWindow = nxagentWindowPtr(X.xcrossing.window); + x.u.keyButtonPointer.rootX = X.xcrossing.x_root; + x.u.keyButtonPointer.rootY = X.xcrossing.y_root; + } + else + { + x.u.keyButtonPointer.rootX = X.xcrossing.x - nxagentOption(RootX); + x.u.keyButtonPointer.rootY = X.xcrossing.y - nxagentOption(RootY); + } + + x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis(); + + mieqEnqueue(&x); + + nxagentDirectInstallColormaps(pScreen); + } + } + + nxagentInputEvent = 1; + + break; + } + case LeaveNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new LeaveNotify event.\n"); + #endif + + if (nxagentOption(Rootless) && X.xcrossing.mode == NotifyNormal && + X.xcrossing.detail != NotifyInferior) + { + nxagentLastEnteredWindow = NULL; + } + + if (nxagentOption(Fullscreen)) + { + if (X.xcrossing.window == nxagentFullscreenWindow && + X.xcrossing.detail != NotifyInferior && + X.xcrossing.mode == NotifyNormal) + { + nxagentUngrabPointerAndKeyboard(&X); + + pScreen = nxagentScreen(X.xcrossing.window); + + minimize = True; + } + } + + if (X.xcrossing.detail != NotifyInferior) + { + pScreen = nxagentScreen(X.xcrossing.window); + + if (pScreen) + { + nxagentDirectUninstallColormaps(pScreen); + } + } + + nxagentInputEvent = 1; + + break; + } + case DestroyNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new DestroyNotify event.\n"); + #endif + + if (nxagentParentWindow != (Window) 0 && + X.xdestroywindow.window == nxagentParentWindow) + { + fprintf(stderr, "Warning: Unhandled destroy notify event received in agent.\n"); + } + + break; + } + case ClientMessage: + { + enum HandleEventResult result; + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new ClientMessage event.\n"); + #endif + + nxagentHandleClientMessageEvent(&X, &result); + + if (result == doCloseSession) + { + closeSession = TRUE; + } + + break; + } + case VisibilityNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new VisibilityNotify event.\n"); + #endif + + if (X.xvisibility.window != nxagentDefaultWindows[0]) + { + Window window = X.xvisibility.window; + + WindowPtr pWin = nxagentWindowPtr(window); + + if (pWin && nxagentWindowPriv(pWin)) + { + if (nxagentWindowPriv(pWin) -> visibilityState != X.xvisibility.state) + { + int value = X.xvisibility.state; + + if (nxagentOption(Rootless) == 1) + { + TraverseTree(pWin, nxagentChangeVisibilityPrivate, &value); + } + else + { + nxagentChangeVisibilityPrivate(pWin, &value); + } + } + } + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Suppressing visibility notify on window [%lx].\n", + X.xvisibility.window); + #endif + + break; + } + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Visibility notify state is [%d] with previous [%d].\n", + X.xvisibility.state, nxagentVisibility); + #endif + + nxagentVisibility = X.xvisibility.state; + + break; + } + case Expose: + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: Going to handle new Expose event.\n"); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: WARNING! Received Expose event " + "for drawable [%lx] geometry [%d, %d, %d, %d] count [%d].\n", + X.xexpose.window, X.xexpose.x, X.xexpose.y, X.xexpose.width, + X.xexpose.height, X.xexpose.count); + #endif + + nxagentHandleExposeEvent(&X); + + break; + } + case GraphicsExpose: + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: Going to handle new GraphicsExpose event.\n"); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: WARNING! Received GraphicsExpose event " + "for drawable [%lx] geometry [%d, %d, %d, %d] count [%d].\n", + X.xgraphicsexpose.drawable, X.xgraphicsexpose.x, X.xgraphicsexpose.y, + X.xgraphicsexpose.width, X.xgraphicsexpose.height, + X.xgraphicsexpose.count); + #endif + + nxagentHandleGraphicsExposeEvent(&X); + + break; + } + case NoExpose: + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: Going to handle new NoExpose event.\n"); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: WARNING! Received NoExpose event for " + "drawable [%lx].\n", X.xnoexpose.drawable); + #endif + + break; + } + case CirculateNotify: + { + /* + * WindowPtr pWin; + * WindowPtr pSib; + * ClientPtr pClient; + + * XID values[2]; + * register XID *value = values; + * Mask mask = 0; + */ + + #ifdef WARNING + fprintf(stderr, "nxagentDispatchEvents: Going to handle new CirculateNotify event.\n"); + #endif + + /* + * FIXME: Do we need this? + * + * pWin = nxagentWindowPtr(X.xcirculate.window); + * + * if (!pWin) + * { + * pWin = nxagentRootlessTopLevelWindow(X.xcirculate.window); + * } + * + * if (!pWin) + * { + * break; + * } + * + * XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + * &root_return, &parent_return, &children_return, &nchildren_return); + * + * nxagentRootlessRestack(children_return, nchildren_return); + */ + + break; + } + case ConfigureNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new ConfigureNotify event.\n"); + #endif + + if (nxagentConfiguredSynchroWindow == X.xconfigure.window) + { + if (nxagentExposeQueue.exposures[nxagentExposeQueue.start].serial != X.xconfigure.x) + { + #ifdef WARNING + fprintf(stderr, "nxagentDispatchEvents: Requested ConfigureNotify changes didn't take place.\n"); + #endif + } + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Received ConfigureNotify and going to call " + "nxagentSynchronizeExpose.\n"); + #endif + + nxagentSynchronizeExpose(); + + break; + } + + nxagentHandleConfigureNotify(&X); + + break; + } + case GravityNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new GravityNotify event.\n"); + #endif + + break; + } + case ReparentNotify: + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new ReparentNotify event.\n"); + #endif + + nxagentHandleReparentNotify(&X); + + break; + } + case UnmapNotify: + { + WindowPtr pWin; + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new UnmapNotify event.\n"); + #endif + + if (nxagentOption(Rootless) == 1) + { + if ((pWin = nxagentRootlessTopLevelWindow(X.xunmap.window)) != NULL || + ((pWin = nxagentWindowPtr(X.xunmap.window)) != NULL && + nxagentWindowTopLevel(pWin) == 1)) + { + nxagentScreenTrap = 1; + + UnmapWindow(pWin, False); + + nxagentScreenTrap = 0; + } + } + + if (nxagentUseNXTrans == 1 && nxagentOption(Rootless) == 0 && + nxagentOption(Nested) == 0 && X.xmap.window != nxagentIconWindow) + { + nxagentVisibility = VisibilityFullyObscured; + } + + break; + } + case MapNotify: + { + WindowPtr pWin; + ClientPtr pClient; + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Going to handle new MapNotify event.\n"); + #endif + + if (nxagentOption(Rootless) == 1) + { + Bool value = 1; + + if ((pWin = nxagentRootlessTopLevelWindow(X.xmap.window)) != NULL || + ((pWin = nxagentWindowPtr(X.xmap.window)) != NULL && + nxagentWindowTopLevel(pWin) == 1)) + { + pClient = wClient(pWin); + + nxagentScreenTrap = 1; + + MapWindow(pWin, pClient); + + nxagentScreenTrap = 0; + } + + if (pWin != NULL) + { + TraverseTree(pWin, nxagentChangeMapPrivate, &value); + } + } + + if (nxagentOption(Fullscreen) == 1) + { + if (X.xmap.window == nxagentIconWindow) + { + pScreen = nxagentScreen(X.xmap.window); + nxagentMaximizeToFullScreen(pScreen); + } + + nxagentVisibility = VisibilityUnobscured; + nxagentVisibilityStop = False; + nxagentVisibilityTimeout = GetTimeInMillis() + 2000; + } + + break; + } + case MappingNotify: + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchEvents: WARNING! Going to handle new MappingNotify event.\n"); + #endif + + break; + } + default: + { + /* + * Let's check if this is a XKB + * state modification event. + */ + + if (nxagentHandleKeyboardEvent(&X) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: WARNING! Unhandled event code [%d].\n", + X.type); + #endif + } + + break; + } + + } /* End of switch (X.type) */ + + } /* End of while (...) */ + + /* + * Send the exposed regions to the clients. + */ + + nxagentForwardRemoteExpose(); + + /* + * Handle the agent window's changes. + */ + + if (closeSession) + { + if (nxagentOption(Persistent)) + { + if (nxagentNoDialogIsRunning) + { + nxagentLaunchDialog(DIALOG_SUSPEND_SESSION); + } + } + else + { + if (nxagentNoDialogIsRunning) + { + nxagentLaunchDialog(DIALOG_KILL_SESSION); + } + } + } + + if (minimize) + { + nxagentWMDetect(); + + if (nxagentWMIsRunning) + { + if (nxagentOption(Fullscreen)) + { + nxagentMinimizeFromFullScreen(pScreen); + } + else + { + XIconifyWindow(nxagentDisplay, nxagentDefaultWindows[0], DefaultScreen(nxagentDisplay)); + } + } + } + + if (switchFullscreen) + { + nxagentSwitchFullscreen(pScreen, !nxagentOption(Fullscreen)); + } + + if (startKbd) + { + if (xkbdRunning) + { + #ifdef NXAGENT_XKBD_DEBUG + fprintf(stderr, "Events: nxkbd now is NOT running: %d, %d\n", + X.xkey.keycode, escapecode); + #endif + + xkbdRunning = False; + + kill(pidkbd, 9); + } + else + { + char kbddisplay[6]; + char *kbdargs[6]; + + strcpy(kbddisplay,":"); + strncat(kbddisplay, display, 4); + + kbdargs[0] = "nxkbd"; + kbdargs[1] = "-geometry"; + kbdargs[2] = "240x70+0+250"; + kbdargs[3] = "-display"; + kbdargs[4] = kbddisplay; + kbdargs[5] = NULL; + + switch (pidkbd = fork()) + { + case 0: + { + execvp(kbdargs[0], kbdargs); + + #ifdef NXAGENT_XKBD_DEBUG + fprintf(stderr, "Events: The execvp of nxkbd process failed.\n"); + #endif + + exit(1); + + break; + } + case -1: + { + #ifdef NXAGENT_XKBD_DEBUG + fprintf(stderr, "Events: Can't fork to run the nxkbd process.\n"); + #endif + + break; + } + default: + { + break; + } + } + + #ifdef NXAGENT_XKBD_DEBUG + fprintf(stderr, "Events: The nxkbd process now running with [%d][%d].\n", + X.xkey.keycode, escapecode); + #endif + + xkbdRunning = True; + } + } + + #ifdef BLOCKS + fprintf(stderr, "[End read]\n"); + #endif + + /* + * Let the underlying X server code + * process the input events. + */ + + #ifdef BLOCKS + fprintf(stderr, "[Begin events]\n"); + #endif + + ProcessInputEvents(); + + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Output pending flag is [%d] critical [%d].\n", + NewOutputPending, CriticalOutputPending); + #endif + + /* + * Write the events to our clients. We may + * flush only in the case of critical output + * but this doesn't seem beneficial. + * + * if (CriticalOutputPending == 1) + * { + * FlushAllOutput(); + * } + */ + + if (NewOutputPending == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentDispatchEvents: Flushed the processed events to clients.\n"); + #endif + + FlushAllOutput(); + } + + #ifdef TEST + + if (nxagentPendingEvents(nxagentDisplay) > 0) + { + fprintf(stderr, "nxagentDispatchEvents: WARNING! More events need to be dispatched.\n"); + } + + #endif + + #ifdef BLOCKS + fprintf(stderr, "[End events]\n"); + #endif +} + +/* + * Functions providing the ad-hoc handling + * of the remote X events. + */ + +int nxagentHandleKeyPress(XEvent *X, enum HandleEventResult *result) +{ + xEvent x; + + if (nxagentXkbState.Initialized == 0) + { + nxagentInitKeyboardState(); + } + + if (nxagentCheckSpecialKeystroke(&X -> xkey, result)) + { + return 1; + } + + nxagentLastEventTime = nxagentLastKeyPressTime = GetTimeInMillis(); + + x.u.u.type = KeyPress; + x.u.u.detail = X -> xkey.keycode; + x.u.keyButtonPointer.time = nxagentLastKeyPressTime; + + nxagentLastServerTime = X -> xkey.time; + + mieqEnqueue(&x); + + CriticalOutputPending = 1; + + return 1; +} + +int nxagentHandlePropertyNotify(XEvent *X) +{ + int resource; + + if (nxagentOption(Rootless) && !nxagentNotifyMatchChangeProperty((XPropertyEvent *) X)) + { + #ifdef TEST + fprintf(stderr, "nxagentHandlePropertyNotify: Property %ld on window %lx.\n", + X -> xproperty.atom, X -> xproperty.window); + #endif + + if (nxagentWindowPtr(X -> xproperty.window) != NULL) + { + resource = NXGetCollectPropertyResource(nxagentDisplay); + + if (resource == -1) + { + #ifdef WARNING + fprintf(stderr, "nxagentHandlePropertyNotify: WARNING! Asyncronous get property queue is full.\n"); + #endif + + return 0; + } + + NXCollectProperty(nxagentDisplay, resource, + X -> xproperty.window, X -> xproperty.atom, 0, + MAX_RETRIEVED_PROPERTY_SIZE, False, AnyPropertyType); + + nxagentPropertyRequests[resource].window = X -> xproperty.window; + nxagentPropertyRequests[resource].property = X -> xproperty.atom; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentHandlePropertyNotify: Failed to look up remote window property.\n"); + } + #endif + } + + return 1; +} + +int nxagentHandleExposeEvent(XEvent *X) +{ + WindowPtr pWin = NULL; + Window window = None; + + RegionRec sum; + RegionRec add; + BoxRec box; + int index = 0; + int overlap = 0; + + #ifdef DEBUG + fprintf(stderr, "nxagentHandleExposeEvent: Checking remote expose events.\n"); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentHandleExposeEvent: Looking for window id [%ld].\n", + X -> xexpose.window); + #endif + + window = X -> xexpose.window; + + pWin = nxagentWindowPtr(window); + + if (pWin != NULL) + { + REGION_INIT(pWin -> drawable.pScreen, &sum, (BoxRec *) NULL, 1); +/* +FIXME: This can be maybe optimized by consuming the + events that do not match the predicate. +*/ + do + { + #ifdef DEBUG + fprintf(stderr, "nxagentHandleExposeEvent: Adding event for window id [%ld].\n", + X -> xexpose.window); + #endif + + box.x1 = pWin -> drawable.x + wBorderWidth(pWin) + X -> xexpose.x; + box.y1 = pWin -> drawable.y + wBorderWidth(pWin) + X -> xexpose.y; + + box.x2 = box.x1 + X -> xexpose.width; + box.y2 = box.y1 + X -> xexpose.height; + + REGION_INIT(pWin -> drawable.pScreen, &add, &box, 1); + + REGION_APPEND(pWin -> drawable.pScreen, &sum, &add); + + REGION_UNINIT(pWin -> drawable.pScreen, &add); + + if (X -> xexpose.count == 0) + { + break; + } + } + while (nxagentCheckEvents(nxagentDisplay, X, nxagentExposurePredicate, + (XPointer) &window) == 1); + + REGION_VALIDATE(pWin -> drawable.pScreen, &sum, &overlap); + + REGION_INTERSECT(pWin->drawable.pScreen, &sum, &sum, + &WindowTable[pWin->drawable.pScreen->myNum]->winSize); + + #ifdef DEBUG + fprintf(stderr, "nxagentHandleExposeEvent: Sending events for window id [%ld].\n", + X -> xexpose.window); + #endif + + /* + * If the agent has already sent auto-generated expose, + * save received exposes for later processing. + */ + + index = nxagentLookupByWindow(pWin); + + if (index == -1) + { + miWindowExposures(pWin, &sum, NullRegion); + } + else + { + REGION_TRANSLATE(pWin -> drawable.pScreen, &sum, -pWin -> drawable.x, -pWin -> drawable.y); + + if (nxagentExposeQueue.exposures[index].remoteRegion == NullRegion) + { + nxagentExposeQueue.exposures[index].remoteRegion = REGION_CREATE(pwin -> drawable.pScreen, NULL, 1); + } + + REGION_UNION(pWin -> drawable.pScreen, nxagentExposeQueue.exposures[index].remoteRegion, + nxagentExposeQueue.exposures[index].remoteRegion, &sum); + + #ifdef TEST + fprintf(stderr, "nxagentHandleExposeEvent: Added region for window [%ld] to position [%d].\n", + nxagentWindow(pWin), index); + #endif + + if (X -> xexpose.count == 0) + { + nxagentExposeQueue.exposures[index].remoteRegionIsCompleted = True; + } + else + { + nxagentExposeQueue.exposures[index].remoteRegionIsCompleted = False; + } + } + + if (nxagentRootTileWindow != NULL) + { + if (nxagentWindowPriv(nxagentRootTileWindow) -> window == nxagentWindowPriv(pWin) -> window && + nxagentSplashCount == 1 && X -> xexpose.count == 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentHandleExposeEvent: Clearing root tile window id [%ld].\n", + nxagentWindowPriv(nxagentRootTileWindow) -> window); + #endif + + XClearWindow(nxagentDisplay, nxagentWindowPriv(nxagentRootTileWindow) -> window); + } + } + + REGION_UNINIT(pWin -> drawable.pScreen, &sum); + } + + return 1; +} + +int nxagentHandleGraphicsExposeEvent(XEvent *X) +{ + /* + * Send an expose event to client, instead of graphics + * expose. If target drawable is a backing pixmap, send + * expose event for the saved window, else do nothing. + */ + + RegionPtr exposeRegion; + BoxRec rect; + WindowPtr pWin; + ScreenPtr pScreen; + StoringPixmapPtr pStoringPixmapRec = NULL; + miBSWindowPtr pBSwindow = NULL; + int drawableType; + + pWin = nxagentWindowPtr(X -> xgraphicsexpose.drawable); + + if (pWin != NULL) + { + drawableType = DRAWABLE_WINDOW; + } + else + { + drawableType = DRAWABLE_PIXMAP; + } + + if (drawableType == DRAWABLE_PIXMAP) + { + pStoringPixmapRec = nxagentFindItemBSPixmapList(X -> xgraphicsexpose.drawable); + + if (pStoringPixmapRec == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleGraphicsExposeEvent: WARNING! Storing pixmap not found.\n"); + #endif + + return 1; + } + + pBSwindow = (miBSWindowPtr) pStoringPixmapRec -> pSavedWindow -> backStorage; + + if (pBSwindow == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleGraphicsExposeEvent: WARNING! Back storage not found.\n"); + #endif + + return 1; + } + + pWin = pStoringPixmapRec -> pSavedWindow; + } + + pScreen = pWin -> drawable.pScreen; + + /* + * Rectangle affected by GraphicsExpose + * event. + */ + + rect.x1 = X -> xgraphicsexpose.x; + rect.y1 = X -> xgraphicsexpose.y; + rect.x2 = rect.x1 + X -> xgraphicsexpose.width; + rect.y2 = rect.y1 + X -> xgraphicsexpose.height; + + exposeRegion = REGION_CREATE(pScreen, &rect, 0); + + if (drawableType == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleGraphicsExposeEvent: Handling GraphicsExpose event on pixmap with id" + " [%lu].\n", X -> xgraphicsexpose.drawable); + #endif + + /* + * The exposeRegion coordinates are relative + * to the pixmap to which GraphicsExpose + * event refers. But the BS coordinates of + * the savedRegion are relative to the + * window. + */ + + REGION_TRANSLATE(pScreen, exposeRegion, pStoringPixmapRec -> backingStoreX, + pStoringPixmapRec -> backingStoreY); + + /* + * We remove from SavedRegion the part + * affected by the GraphicsExpose event. + */ + + REGION_SUBTRACT(pScreen, &(pBSwindow -> SavedRegion), &(pBSwindow -> SavedRegion), + exposeRegion); + } + + /* + * Store the exposeRegion in order to send + * the expose event later. The coordinates + * must be relative to the screen. + */ + + REGION_TRANSLATE(pScreen, exposeRegion, pWin -> drawable.x, pWin -> drawable.y); + + REGION_UNION(pScreen, nxagentRemoteExposeRegion, nxagentRemoteExposeRegion, exposeRegion); + + REGION_DESTROY(pScreen, exposeRegion); + + return 1; +} + +int nxagentHandleClientMessageEvent(XEvent *X, enum HandleEventResult *result) +{ + ScreenPtr pScreen; + WindowPtr pWin; + xEvent x; + + *result = doNothing; + + #ifdef TEST + fprintf(stderr, "nxagentHandleClientMessageEvent: ClientMessage event window [%ld] with " + "type [%ld] format [%d].\n", X -> xclient.window, X -> xclient.message_type, + X -> xclient.format); + #endif + + /* + * If window is 0, message_type is 0 and format is + * 32 then we assume event is coming from proxy. + */ + + if (X -> xclient.window == 0 && + X -> xclient.message_type == 0 && + X -> xclient.format == 32) + { + nxagentHandleProxyEvent(X); + + return 1; + } + + if (nxagentOption(Rootless)) + { + Atom message_type = nxagentRemoteToLocalAtom(X -> xclient.message_type); + + if (!ValidAtom(message_type)) + { + #ifdef WARNING + fprintf(stderr, "nxagentHandleClientMessageEvent: WARNING Invalid type in client message.\n"); + #endif + + return 0; + } + + pWin = nxagentWindowPtr(X -> xclient.window); + + if (pWin == NULL) + { + #ifdef WARNING + fprintf(stderr, "WARNING: Invalid window in ClientMessage.\n"); + #endif + + return 0; + } + + if (message_type == MakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), False)) + { + char *message_data; + + x.u.u.type = ClientMessage; + x.u.u.detail = X -> xclient.format; + + x.u.clientMessage.window = pWin -> drawable.id; + x.u.clientMessage.u.l.type = message_type; + x.u.clientMessage.u.l.longs0 = nxagentRemoteToLocalAtom(X -> xclient.data.l[0]); + x.u.clientMessage.u.l.longs1 = GetTimeInMillis(); + + if (!ValidAtom(x.u.clientMessage.u.l.longs0)) + { + #ifdef WARNING + fprintf(stderr, "nxagentHandleClientMessageEvent: WARNING Invalid value in client message " + "of type WM_PROTOCOLS.\n"); + #endif + + return 0; + } + else + { + message_data = validateString(NameForAtom(x.u.clientMessage.u.l.longs0)); + } + + #ifdef TEST + fprintf(stderr, "nxagentHandleClientMessageEvent: Sent client message of type WM_PROTOCOLS " + "and value [%s].\n", message_data); + #endif + + TryClientEvents(wClient(pWin), &x, 1, 1, 1, 0); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentHandleClientMessageEvent: Ignored message type %ld [%s].\n", + (long int) message_type, validateString(NameForAtom(message_type))); + #endif + + return 0; + } + + return 1; + } + + if (X -> xclient.message_type == nxagentAtoms[1]) /* WM_PROTOCOLS */ + { + Atom deleteWMatom, wmAtom; + + wmAtom = (Atom) X -> xclient.data.l[0]; + + deleteWMatom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */ + + if (wmAtom == deleteWMatom) + { + if (nxagentOnce && (nxagentClients == 0)) + { + GiveUp(0); + } + else + { + #ifdef TEST + fprintf(stderr, "Events: WM_DELETE_WINDOW arrived Atom = %ld.\n", wmAtom); + #endif + + if (X -> xclient.window == nxagentIconWindow) + { + pScreen = nxagentScreen(X -> xmap.window); + + nxagentMaximizeToFullScreen(pScreen); + } + + if (X -> xclient.window == (nxagentOption(Fullscreen) ? + nxagentIconWindow : nxagentDefaultWindows[0])) + { + *result = doCloseSession; + } + } + } + } + + return 1; +} + +int nxagentHandleKeyboardEvent(XEvent *X) +{ + XkbEvent *xkbev = (XkbEvent *) X; + + #ifdef TEST + fprintf(stderr, "nxagentHandleKeyboardEvent: Handling event with caps [%d] num [%d] locked [%d].\n", + nxagentXkbState.Caps, nxagentXkbState.Num, nxagentXkbState.Locked); + #endif + + if (xkbev -> type == nxagentXkbInfo.EventBase + XkbEventCode && + xkbev -> any.xkb_type == XkbStateNotify) + { + nxagentXkbState.Locked = xkbev -> state.locked_mods; + + #ifdef TEST + fprintf(stderr, "nxagentHandleKeyboardEvent: Updated XKB locked modifier bits to [%x].\n", + nxagentXkbState.Locked); + #endif + + nxagentXkbState.Initialized = 1; + + if (nxagentXkbState.Caps == 0 && + (nxagentXkbState.Locked & CAPSFLAG_IN_EVENT)) + { + nxagentXkbState.Caps = 1; + + #ifdef TEST + fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [66] to engage capslock.\n"); + #endif + + nxagentSendFakeKey(66); + } + + if (nxagentXkbState.Caps == 1 && + !(nxagentXkbState.Locked & CAPSFLAG_IN_EVENT)) + { + nxagentXkbState.Caps = 0; + + #ifdef TEST + fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [66] to release capslock.\n"); + #endif + + nxagentSendFakeKey(66); + } + + if (nxagentXkbState.Num == 0 && + (nxagentXkbState.Locked & NUMFLAG_IN_EVENT)) + { + nxagentXkbState.Num = 1; + + #ifdef TEST + fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [77] to engage numlock.\n"); + #endif + + nxagentSendFakeKey(77); + } + + if (nxagentXkbState.Num == 1 && + !(nxagentXkbState.Locked & NUMFLAG_IN_EVENT)) + { + nxagentXkbState.Num = 0; + + #ifdef TEST + fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [77] to release numlock.\n"); + #endif + + nxagentSendFakeKey(77); + } + + return 1; + } + + return 0; +} + +int nxagentHandleProxyEvent(XEvent *X) +{ + switch (X -> xclient.data.l[0]) + { + case NXNoSplitNotify: + case NXStartSplitNotify: + { + /* + * We should never receive such events + * in the event loop, as they should + * be caught at the time the split is + * initiated. + */ + + #ifdef PANIC + + int client = (int) X -> xclient.data.l[1]; + + if (X -> xclient.data.l[0] == NXNoSplitNotify) + { + fprintf(stderr, "nxagentHandleProxyEvent: PANIC! NXNoSplitNotify received " + "with client [%d].\n", client); + } + else + { + fprintf(stderr, "nxagentHandleProxyEvent: PANIC! NXStartSplitNotify received " + "with client [%d].\n", client); + } + + #endif + + return 1; + } + case NXCommitSplitNotify: + { + /* + * We need to commit an image. Image can be the + * result of a PutSubImage() generated by Xlib, + * so there can be more than a single image to + * commit, even if only one PutImage was perfor- + * med by the agent. + */ + + int client = (int) X -> xclient.data.l[1]; + int request = (int) X -> xclient.data.l[2]; + int position = (int) X -> xclient.data.l[3]; + + #ifdef TEST + fprintf(stderr, "nxagentHandleProxyEvent: NXCommitSplitNotify received with " + "client [%d] request [%d] and position [%d].\n", + client, request, position); + #endif + + nxagentHandleCommitSplitEvent(client, request, position); + + return 1; + } + case NXEndSplitNotify: + { + /* + * All images for the split were transferred and + * we need to restart the client. + */ + + int client = (int) X -> xclient.data.l[1]; + + #ifdef TEST + fprintf(stderr, "nxagentHandleProxyEvent: NXEndSplitNotify received with " + "client [%d].\n", client); + #endif + + nxagentHandleEndSplitEvent(client); + + return 1; + } + case NXEmptySplitNotify: + { + /* + * All splits have been completed and none remain. + */ + + #ifdef TEST + fprintf(stderr, "nxagentHandleProxyEvent: NXEmptySplitNotify received.\n"); + #endif + + nxagentHandleEmptySplitEvent(); + + return 1; + } + case NXCollectPropertyNotify: + { + #ifdef TEST + int resource = (int) X -> xclient.data.l[1]; + + fprintf(stderr, "nxagentHandleProxyEvent: NXCollectPropertyNotify received with resource [%d].\n", + resource); + #endif + + nxagentHandleCollectPropertyEvent(X); + + return 1; + } + case NXCollectGrabPointerNotify: + { + int resource = (int) X -> xclient.data.l[1]; + + #ifdef TEST + fprintf(stderr, "nxagentHandleProxyEvent: NXCollectGrabPointerNotify received with resource [%d].\n", + resource); + #endif + + nxagentHandleCollectGrabPointerEvent(resource); + + return 1; + } + case NXCollectInputFocusNotify: + { + int resource = (int) X -> xclient.data.l[1]; + + /* + * This is not used at the present moment. + */ + + #ifdef TEST + fprintf(stderr, "nxagentHandleProxyEvent: NXCollectInputFocusNotify received with resource [%d].\n", + resource); + #endif + + nxagentHandleCollectInputFocusEvent(resource); + + return 1; + } + default: + { + /* + * Not a recognized ClientMessage event. + */ + + #ifdef WARNING + fprintf(stderr, "nxagentHandleProxyEvent: WARNING! Not a recognized ClientMessage proxy event [%d].\n", + (int) X -> xclient.data.l[0]); + #endif + + return 0; + } + } +} + +/* + * In this function it is assumed that we never + * get a configure with both stacking order and + * geometry changed, this way we can ignore + * stacking changes if the geometry has changed. + */ + +int nxagentCheckWindowConfiguration(XConfigureEvent* X) +{ + static int x = 0; + static int y = 0; + static int width = 0; + static int height = 0; + static Window win = None; + Bool geometryChanged = False; + + XlibWindow root_return = 0; + XlibWindow parent_return = 0; + XlibWindow *children_return = NULL; + unsigned int nchildren_return = 0; + Status result; + + WindowPtr pWin; + + pWin = nxagentWindowPtr(X -> window); + + /* + * This optimization has some problems to + * work in rootless mode inside NXWin. To + * verify this you can launch xterm and + * another application, f.e. firefox. By + * raising xterm above firefox, the stack + * order seems to become incoherent showing + * the underneath window content in the + * overlapping area when the mouse botton is + * pressed with the pointer inside of such area. + * + * if ((pWin != NULL) && X -> override_redirect == 0) + * { + * return 1; + * } + * + */ + + if (win == X -> window) + { + if (x != X -> x || + y != X -> y || + width != X -> width || + height != X -> height) + { + geometryChanged = True; + } + } + + win = X -> window; + + x = X -> x; + y = X -> y; + width = X -> width; + height = X -> height; + + if (geometryChanged) + { + #ifdef TEST + fprintf(stderr, "nxagentCheckWindowConfiguration: Configure frame. No restack.\n"); + #endif + + return 1; + } + + #ifdef TEST + { + WindowPtr pSib; + + fprintf(stderr, "nxagentCheckWindowConfiguration: Before restacking top level window [%p]\n", + (void *) nxagentWindowPtr(X -> window)); + + for (pSib = WindowTable[0] -> firstChild; pSib; pSib = pSib -> nextSib) + { + fprintf(stderr, "nxagentCheckWindowConfiguration: Top level window: [%p].\n", + (void *) pSib); + } + } + #endif + + result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + &root_return, &parent_return, &children_return, &nchildren_return); + + if (result) + { + nxagentRootlessRestack(children_return, nchildren_return); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckWindowConfiguration: WARNING! Failed QueryTree request.\n"); + #endif + } + + if (result && nchildren_return) + { + XFree(children_return); + } + + #if 0 + fprintf(stderr, "nxagentCheckWindowConfiguration: Trees match: %s\n", + nxagentRootlessTreesMatch() ? "Yes" : "No"); + #endif + + return 1; +} + +int nxagentHandleConfigureNotify(XEvent* X) +{ + if (nxagentOption(Rootless) == True) + { + ClientPtr pClient; + WindowPtr pWinWindow; + WindowPtr pWin; + xEvent x; + int sendEventAnyway = 0; + + pWinWindow = nxagentWindowPtr(X -> xconfigure.window); + + #ifdef TEST + { + WindowPtr pWinEvent = nxagentWindowPtr(X -> xconfigure.event); + + fprintf(stderr, "nxagentHandleConfigureNotify: Generating window is [%p][%ld] target [%p][%ld].\n", + (void *) pWinEvent, X -> xconfigure.event, (void *) pWinWindow, X -> xconfigure.window); + } + #endif + + #ifdef TEST + fprintf(stderr, "nxagentHandleConfigureNotify: New configuration for window [%p][%ld] is [%d][%d][%d][%d] " + "send_event [%i].\n", (void *) pWinWindow, X -> xconfigure.window, + X -> xconfigure.x, X -> xconfigure.y, X -> xconfigure.width, + X -> xconfigure.height, X -> xconfigure.send_event); + #endif + + if ((pWin = nxagentRootlessTopLevelWindow(X -> xconfigure.window)) != NULL) + { + /* + * Cheking for new geometry or stacking order changes. + */ + + nxagentCheckWindowConfiguration((XConfigureEvent*)X); + + return 1; + } + + if (nxagentWindowTopLevel(pWinWindow) && !X -> xconfigure.override_redirect) + { + XID values[5]; + Mask mask = 0; + + register XID *value = values; + + pClient = wClient(pWinWindow); + + if (X -> xconfigure.send_event || !nxagentWMIsRunning || + X -> xconfigure.override_redirect) + { + *value++ = (XID)X -> xconfigure.x; + *value++ = (XID)X -> xconfigure.y; + + /* + * nxagentWindowPriv(pWinWindow)->x = X -> xconfigure.x; + * nxagentWindowPriv(pWinWindow)->y = X -> xconfigure.y; + */ + + mask |= CWX | CWY; + } + + *value++ = (XID)X -> xconfigure.width; + *value++ = (XID)X -> xconfigure.height; + *value++ = (XID)X -> xconfigure.border_width; + + /* + * We don't need width and height here. + * + * nxagentWindowPriv(pWinWindow)->width = X -> xconfigure.width; + * nxagentWindowPriv(pWinWindow)->height = X -> xconfigure.height; + */ + + mask |= CWHeight | CWWidth | CWBorderWidth; + + nxagentScreenTrap = 1; + + ConfigureWindow(pWinWindow, mask, (XID *) values, pClient); + + nxagentScreenTrap = 0; + + nxagentCheckWindowConfiguration((XConfigureEvent*)X); + + /* + * This workaround should help with + * Java 1.6.0 that seems to ignore + * non-synthetic events. + */ + + if (nxagentOption(ClientOs) == ClientOsWinnt) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConfigureNotify: Apply workaround for NXWin.\n"); + #endif + + sendEventAnyway = 1; + } + + if (sendEventAnyway || X -> xconfigure.send_event) + { + x.u.u.type = X -> xconfigure.type; + x.u.u.type |= 0x80; + + x.u.configureNotify.event = pWinWindow -> drawable.id; + x.u.configureNotify.window = pWinWindow -> drawable.id; + + if (pWinWindow -> nextSib) + { + x.u.configureNotify.aboveSibling = pWinWindow -> nextSib -> drawable.id; + } + else + { + x.u.configureNotify.aboveSibling = None; + } + + x.u.configureNotify.x = X -> xconfigure.x; + x.u.configureNotify.y = X -> xconfigure.y; + x.u.configureNotify.width = X -> xconfigure.width; + x.u.configureNotify.height = X -> xconfigure.height; + x.u.configureNotify.borderWidth = X -> xconfigure.border_width; + x.u.configureNotify.override = X -> xconfigure.override_redirect; + + TryClientEvents(pClient, &x, 1, 1, 1, 0); + } + + return 1; + } + } + else + { + /* + * Save the position of the agent default window. Don't + * save the values if the agent is in fullscreen mode. + * + * If we use these values to restore the position of a + * window after that we have dynamically changed the + * fullscreen attribute, depending on the behaviour of + * window manager, we could be not able to place the + * window exactly in the requested position, so let the + * window manager do the job for us. + */ + + ScreenPtr pScreen = nxagentScreen(X -> xconfigure.window); + + Bool doRandR = False; + struct timeval timeout; + + if (X -> xconfigure.window == nxagentDefaultWindows[pScreen -> myNum]) + { + if (nxagentOption(Fullscreen) == 0) + { + if (nxagentOption(DesktopResize) == 1) + { + if (nxagentOption(Width) != X -> xconfigure.width || + nxagentOption(Height) != X -> xconfigure.height) + { + Bool newEvents = False; + + doRandR = True; + + NXFlushDisplay(nxagentDisplay, NXFlushLink); + + do + { + newEvents = False; + + timeout.tv_sec = 0; + timeout.tv_usec = 500 * 1000; + + nxagentWaitEvents(nxagentDisplay, &timeout); + + /* + * This should also flush + * the NX link for us. + */ + + XSync(nxagentDisplay, 0); + + while (XCheckTypedWindowEvent(nxagentDisplay, nxagentDefaultWindows[pScreen -> myNum], + ConfigureNotify, X)) + { + newEvents = True; + } + + } while (newEvents); + } + } + + if (nxagentWMIsRunning == 0 || X -> xconfigure.send_event) + { + nxagentChangeOption(X, X -> xconfigure.x); + nxagentChangeOption(Y, X -> xconfigure.y); + } + + if (nxagentOption(Shadow) == 1 && nxagentOption(DesktopResize) == 1 && + (nxagentOption(Width) != X -> xconfigure.width || + nxagentOption(Height) != X -> xconfigure.height)) + { + nxagentShadowResize = 1; + } + + nxagentChangeOption(Width, X -> xconfigure.width); + nxagentChangeOption(Height, X -> xconfigure.height); + + nxagentChangeOption(ViewportXSpan, (int) X -> xconfigure.width - + (int) nxagentOption(RootWidth)); + nxagentChangeOption(ViewportYSpan, (int) X -> xconfigure.height - + (int) nxagentOption(RootHeight)); + + nxagentMoveViewport(pScreen, 0, 0); + + if (nxagentOption(Shadow) == 1 || + (nxagentOption(Width) == nxagentOption(RootWidth) && + nxagentOption(Height) == nxagentOption(RootHeight))) + { + doRandR = 0; + } + + if (doRandR) + { + #ifdef TEST + fprintf(stderr,"nxagentHandleConfigureNotify: Width %d Height %d.\n", + nxagentOption(Width), nxagentOption(Height)); + #endif + + nxagentRRSetScreenConfig(screenInfo.screens[DefaultScreen(nxagentDisplay)], + nxagentOption(Width), nxagentOption(Height)); + } + } + + return 1; + } + } + + return 0; +} + +int nxagentHandleReparentNotify(XEvent* X) +{ + ScreenPtr pScreen = nxagentScreen(X -> xreparent.window); + + #ifdef TEST + fprintf(stderr, "nxagentHandleReparentNotify: Going to handle a new reparent event.\n"); + #endif + + if (nxagentOption(Rootless)) + { + WindowPtr pWin; + + XlibWindow w; + XlibWindow root_return = 0; + XlibWindow parent_return = 0; + XlibWindow *children_return = NULL; + unsigned int nchildren_return = 0; + Status result; + + pWin = nxagentWindowPtr(X -> xreparent.window); + + #ifdef TEST + + { + WindowPtr pParent = nxagentWindowPtr(X -> xreparent.parent); + WindowPtr pEvent = nxagentWindowPtr(X -> xreparent.event); + + fprintf(stderr, "nxagentHandleReparentNotify: event %p[%lx] window %p[%lx] parent %p[%lx] at (%d, %d)\n", + (void*)pEvent, X -> xreparent.event, (void*)pWin, X -> xreparent.window, + (void*)pParent, X -> xreparent.parent, X -> xreparent.x, X -> xreparent.y); + } + + #endif + + if (nxagentWindowTopLevel(pWin)) + { + /* + * If the window manager reparents our top level + * window, we need to know the new top level + * ancestor. + */ + + w = None; + parent_return = X -> xreparent.parent; + + while (parent_return != RootWindow(nxagentDisplay, 0)) + { + w = parent_return; + result = XQueryTree(nxagentDisplay, w, &root_return, + &parent_return, &children_return, &nchildren_return); + + if (!result) + { + #ifdef WARNING + fprintf(stderr, "nxagentHandleReparentNotify: WARNING! Failed QueryTree request.\n"); + #endif + } + + if (result && children_return) + { + XFree(children_return); + } + } + + if (w && !nxagentWindowPtr(w)) + { + XSelectInput(nxagentDisplay, w, StructureNotifyMask); + + nxagentRootlessAddTopLevelWindow(pWin, w); + + #ifdef TEST + fprintf(stderr, "nxagentHandleReparentNotify: new top level window [%ld].\n", w); + fprintf(stderr, "nxagentHandleReparentNotify: reparented window [%ld].\n", + X -> xreparent.window); + #endif + + result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + &root_return, &parent_return, &children_return, &nchildren_return); + + if (result) + { + nxagentRootlessRestack(children_return, nchildren_return); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentHandleReparentNotify: WARNING! Failed QueryTree request.\n"); + #endif + } + + if (result && nchildren_return) + { + XFree(children_return); + } + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentHandleReparentNotify: Window at [%p] has been reparented to [%ld]" + " top level parent [%ld].\n", (void *) pWin, X -> xreparent.parent, w); + #endif + + nxagentRootlessDelTopLevelWindow(pWin); + } + } + + return 1; + } + else + { + /* + * This code is supposed to detect if a window manager + * is running but in some cases it may be unreliable. + * Each window manager behaves differently so the check + * can fail for some less common WMs. + */ + + if (!nxagentWMIsRunning && nxagentOption(Fullscreen) && + X -> xreparent.window == nxagentDefaultWindows[pScreen -> myNum]) + { + #ifdef WARNING + fprintf(stderr, "Warning: The agent window was reparented. Is a " + "window manager running?\n"); + #endif + + /* + * If no window manager is running and we are supposed to + * be in fullscreen mode then don't wait for the reparent + * event. We can assume that there is an undetected window + * manager and, as switching to fullscreen could have fail- + * ed, we try it again. + */ + + nxagentSwitchFullscreen(pScreen, True); + + nxagentWMIsRunning = True; + } + else if (nxagentWMIsRunning && X -> xreparent.window == + nxagentDefaultWindows[pScreen -> myNum] && X -> xreparent.parent == + RootWindow(nxagentDisplay, (pScreen -> myNum))) + { + #ifdef WARNING + + fprintf(stderr, "Warning: The agent window has been reparented to the root.\n"); + + fprintf(stderr, "Warning: No window manager seems to be running.\n"); + + #endif + + /* + * The agent window was unexpectedly reparented + * to the root window. We assume that the window + * manager was terminated. + */ + + nxagentWMIsRunning = False; + } + } + + return 1; +} + +void nxagentEnableKeyboardEvents() +{ + int i; + Mask mask; + + nxagentGetDefaultEventMask(&mask); + + mask |= NXAGENT_KEYBOARD_EVENT_MASK; + + nxagentSetDefaultEventMask(mask); + + for (i = 0; i < nxagentNumScreens; i++) + { + XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask); + } + + XkbSelectEvents(nxagentDisplay, XkbUseCoreKbd, + NXAGENT_KEYBOARD_EXTENSION_EVENT_MASK, + NXAGENT_KEYBOARD_EXTENSION_EVENT_MASK); +} + +void nxagentDisableKeyboardEvents() +{ + int i; + Mask mask; + + nxagentGetDefaultEventMask(&mask); + + mask &= ~NXAGENT_KEYBOARD_EVENT_MASK; + + nxagentSetDefaultEventMask(mask); + + for (i = 0; i < nxagentNumScreens; i++) + { + XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask); + } + + XkbSelectEvents(nxagentDisplay, XkbUseCoreKbd, 0x0, 0x0); +} + +void nxagentEnablePointerEvents() +{ + int i; + Mask mask; + + nxagentGetDefaultEventMask(&mask); + + mask |= NXAGENT_POINTER_EVENT_MASK; + + nxagentSetDefaultEventMask(mask); + + for (i = 0; i < nxagentNumScreens; i++) + { + XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask); + } +} + +void nxagentDisablePointerEvents() +{ + int i; + Mask mask; + + nxagentGetDefaultEventMask(&mask); + + mask &= ~NXAGENT_POINTER_EVENT_MASK; + + nxagentSetDefaultEventMask(mask); + + for (i = 0; i < nxagentNumScreens; i++) + { + XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask); + } +} + +void nxagentSendFakeKey(int key) +{ + xEvent fake; + Time now; + + now = GetTimeInMillis(); + + fake.u.u.type = KeyPress; + fake.u.u.detail = key; + fake.u.keyButtonPointer.time = now; + + mieqEnqueue(&fake); + + fake.u.u.type = KeyRelease; + fake.u.u.detail = key; + fake.u.keyButtonPointer.time = now; + + mieqEnqueue(&fake); +} + +int nxagentInitKeyboardState() +{ + XEvent X; + + unsigned int modifiers; + + XkbEvent *xkbev = (XkbEvent *) &X; + + #ifdef TEST + fprintf(stderr, "nxagentInitKeyboardState: Initializing XKB state.\n"); + #endif + + XkbGetIndicatorState(nxagentDisplay, XkbUseCoreKbd, &modifiers); + + xkbev -> state.locked_mods = 0x0; + + if (modifiers & CAPSFLAG_IN_REPLY) + { + xkbev -> state.locked_mods |= CAPSFLAG_IN_EVENT; + } + + if (modifiers & NUMFLAG_IN_REPLY) + { + xkbev -> state.locked_mods |= NUMFLAG_IN_EVENT; + } + + #ifdef TEST + fprintf(stderr, "nxagentInitKeyboardState: Assuming XKB locked modifier bits [%x].\n", + xkbev -> state.locked_mods); + #endif + + xkbev -> type = nxagentXkbInfo.EventBase + XkbEventCode; + xkbev -> any.xkb_type = XkbStateNotify; + + nxagentHandleKeyboardEvent(&X); + + return 1; +} + +int nxagentWaitForResource(GetResourceFuncPtr pGetResource, PredicateFuncPtr pPredicate) +{ + int resource; + + while ((resource = (*pGetResource)(nxagentDisplay)) == -1) + { + if (nxagentWaitEvents(nxagentDisplay, NULL) == -1) + { + return -1; + } + + nxagentDispatchEvents(pPredicate); + } + + return resource; +} + +void nxagentGrabPointerAndKeyboard(XEvent *X) +{ + unsigned long now; + + int resource; + + #ifdef TEST + fprintf(stderr, "nxagentGrabPointerAndKeyboard: Grabbing pointer and keyboard with event at [%p].\n", + (void *) X); + #endif + + if (X != NULL) + { + now = X -> xcrossing.time; + } + else + { + now = CurrentTime; + } + + #ifdef TEST + fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to grab the keyboard in context [B1].\n"); + #endif + + XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow, + True, GrabModeAsync, GrabModeAsync, now); + + #ifdef TEST + fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to grab the pointer in context [B2].\n"); + #endif + + resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, + nxagentCollectGrabPointerPredicate); + + NXCollectGrabPointer(nxagentDisplay, resource, + nxagentFullscreenWindow, True, NXAGENT_POINTER_EVENT_MASK, + GrabModeAsync, GrabModeAsync, None, None, now); + + /* + * This should not be needed. + * + * XGrabKey(nxagentDisplay, AnyKey, AnyModifier, nxagentFullscreenWindow, + * True, GrabModeAsync, GrabModeAsync); + */ + + if (X != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to force focus in context [B4].\n"); + #endif + + XSetInputFocus(nxagentDisplay, nxagentFullscreenWindow, + RevertToParent, now); + } +} + +void nxagentUngrabPointerAndKeyboard(XEvent *X) +{ + unsigned long now; + + #ifdef TEST + fprintf(stderr, "nxagentUngrabPointerAndKeyboard: Ungrabbing pointer and keyboard with event at [%p].\n", + (void *) X); + #endif + + if (X != NULL) + { + now = X -> xcrossing.time; + } + else + { + now = CurrentTime; + } + + #ifdef TEST + fprintf(stderr, "nxagentUngrabPointerAndKeyboard: Going to ungrab the keyboard in context [B5].\n"); + #endif + + XUngrabKeyboard(nxagentDisplay, now); + + #ifdef TEST + fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to ungrab the pointer in context [B6].\n"); + #endif + + XUngrabPointer(nxagentDisplay, now); +} + +void nxagentDeactivatePointerGrab() +{ + GrabPtr grab = inputInfo.pointer -> grab; + + XButtonEvent X; + + if (grab) + { + X.type = ButtonRelease; + X.serial = 0; + X.send_event = FALSE; + X.time = currentTime.milliseconds; + X.display = nxagentDisplay; + X.window = nxagentWindow(grab -> window); + X.root = RootWindow(nxagentDisplay, 0); + X.subwindow = 0; + X.x = X.y = X.x_root = X.y_root = 0; + X.state = 0x100; + X.button = 1; + X.same_screen = TRUE; + + XPutBackEvent(nxagentDisplay, (XEvent*)&X); + } +} + +Bool nxagentCollectGrabPointerPredicate(Display *display, XEvent *X, XPointer ptr) +{ + return (X -> xclient.window == 0 && + X -> xclient.message_type == 0 && + X -> xclient.format == 32 && + X -> xclient.data.l[0] == NXCollectGrabPointerNotify); +} + +void nxagentHandleCollectGrabPointerEvent(int resource) +{ + int status; + + if (NXGetCollectedGrabPointer(nxagentDisplay, resource, &status) == 0) + { + #ifdef PANIC + fprintf(stderr, "nxagentHandleCollectGrabPointerEvent: PANIC! Failed to get GrabPointer " + "reply for resource [%d].\n", resource); + #endif + } +} + +void nxagentHandleCollectPropertyEvent(XEvent *X) +{ + Window window; + Atom property; + Atom atomReturnType; + int resultFormat; + unsigned long ulReturnItems; + unsigned long ulReturnBytesLeft; + unsigned char *pszReturnData = NULL; + int result; + int resource; + + resource = X -> xclient.data.l[1]; + + if (X -> xclient.data.l[2] == False) + { + #ifdef DEBUG + fprintf (stderr, "nxagentHandleCollectPropertyEvent: Failed to get reply data for client [%d].\n", + resource); + #endif + + return; + } + + if (resource == nxagentLastClipboardClient) + { + nxagentCollectPropertyEvent(resource); + } + else + { + result = NXGetCollectedProperty(nxagentDisplay, + resource, + &atomReturnType, + &resultFormat, + &ulReturnItems, + &ulReturnBytesLeft, + &pszReturnData); + + if (result == True) + { + window = nxagentPropertyRequests[resource].window; + property = nxagentPropertyRequests[resource].property; + + nxagentImportProperty(window, property, atomReturnType, resultFormat, + ulReturnItems, ulReturnBytesLeft, pszReturnData); + } + + if (result == 0) + { + #ifdef DEBUG + fprintf (stderr, "nxagentHandleCollectPropertyEvent: Failed to get reply data for client [%d].\n", + resource); + #endif + } + + if (pszReturnData != NULL) + { + XFree(pszReturnData); + } + + return; + } +} + +void nxagentSynchronizeExpose(void) +{ + WindowPtr pWin; + + if (nxagentExposeQueue.length <= 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeExpose: PANIC! Called with nxagentExposeQueue.length [%d].\n", + nxagentExposeQueue.length); + #endif + + return; + } + + pWin = nxagentExposeQueueHead.pWindow; + + if (pWin) + { + if ((nxagentExposeQueueHead.localRegion) != NullRegion) + { + REGION_TRANSLATE(pWin -> drawable.pScreen, (nxagentExposeQueueHead.localRegion), + pWin -> drawable.x, pWin -> drawable.y); + } + + if ((nxagentExposeQueueHead.remoteRegion) != NullRegion) + { + REGION_TRANSLATE(pWin -> drawable.pScreen, (nxagentExposeQueueHead.remoteRegion), + pWin -> drawable.x, pWin -> drawable.y); + } + + if ((nxagentExposeQueueHead.localRegion) != NullRegion && + (nxagentExposeQueueHead.remoteRegion) != NullRegion) + { + REGION_SUBTRACT(pWin -> drawable.pScreen, (nxagentExposeQueueHead.remoteRegion), + (nxagentExposeQueueHead.remoteRegion), + (nxagentExposeQueueHead.localRegion)); + + if (REGION_NIL(nxagentExposeQueueHead.remoteRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeExpose: Going to call miWindowExposures" + " for window [%ld] - rects [%ld].\n", nxagentWindow(pWin), + REGION_NUM_RECTS(nxagentExposeQueueHead.remoteRegion)); + #endif + + miWindowExposures(pWin, nxagentExposeQueueHead.remoteRegion, NullRegion); + } + } + } + + nxagentExposeQueueHead.pWindow = NULL; + + if (nxagentExposeQueueHead.localRegion != NullRegion) + { + REGION_DESTROY(nxagentDefaultScreen, nxagentExposeQueueHead.localRegion); + } + + nxagentExposeQueueHead.localRegion = NullRegion; + + if (nxagentExposeQueueHead.remoteRegion != NullRegion) + { + REGION_DESTROY(nxagentDefaultScreen, nxagentExposeQueueHead.remoteRegion); + } + + nxagentExposeQueueHead.remoteRegion = NullRegion; + + nxagentExposeQueueHead.remoteRegionIsCompleted = False; + + nxagentExposeQueue.start = (nxagentExposeQueue.start + 1) % EXPOSED_SIZE; + + nxagentExposeQueue.length--; + + return; +} + +int nxagentLookupByWindow(WindowPtr pWin) +{ + int i; + int j; + + for (j = 0; j < nxagentExposeQueue.length; j++) + { + i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE; + + if (nxagentExposeQueue.exposures[i].pWindow == pWin && + !nxagentExposeQueue.exposures[i].remoteRegionIsCompleted) + { + return i; + } + } + + return -1; +} + +void nxagentRemoveDuplicatedKeys(XEvent *X) +{ + _XQEvent *prev; + _XQEvent *qelt; + + _XQEvent *qeltKeyRelease; + _XQEvent *prevKeyRelease; + + KeyCode lastKeycode = X -> xkey.keycode; + + qelt = nxagentDisplay -> head; + + if (qelt == NULL) + { + #ifdef TEST + + int more; + + fprintf(stderr, "nxagentRemoveDuplicatedKeys: Trying to read more events " + "from the X server.\n"); + + more = nxagentReadEvents(nxagentDisplay); + + if (more > 0) + { + fprintf(stderr, "nxagentRemoveDuplicatedKeys: Successfully read more events " + "from the X server.\n"); + } + + #else + + nxagentReadEvents(nxagentDisplay); + + #endif + + qelt = nxagentDisplay -> head; + } + + if (qelt != NULL) + { + prev = qeltKeyRelease = prevKeyRelease = NULL; + + LockDisplay(nxagentDisplay); + + while (qelt != NULL) + { + if (qelt -> event.type == KeyRelease || + qelt -> event.type == KeyPress) + { + if (qelt -> event.xkey.keycode != lastKeycode || + (qelt -> event.type == KeyPress && qeltKeyRelease == NULL) || + (qelt -> event.type == KeyRelease && qeltKeyRelease != NULL)) + { + break; + } + + if (qelt -> event.type == KeyRelease) + { + prevKeyRelease = prev; + + qeltKeyRelease = qelt; + } + else if (qelt -> event.type == KeyPress) + { + _XDeq(nxagentDisplay, prev, qelt); + + qelt = prev -> next; + + if (prev == qeltKeyRelease) + { + prev = prevKeyRelease; + } + + _XDeq(nxagentDisplay, prevKeyRelease, qeltKeyRelease); + + qeltKeyRelease = prevKeyRelease = NULL; + + continue; + } + } + + prev = qelt; + + qelt = qelt -> next; + } + + UnlockDisplay(nxagentDisplay); + } +} + +void nxagentInitRemoteExposeRegion(void) +{ + if (nxagentRemoteExposeRegion == NULL) + { + nxagentRemoteExposeRegion = REGION_CREATE(pWin -> drawable.pScreen, NULL, 1); + + if (nxagentRemoteExposeRegion == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentInitRemoteExposeRegion: PANIC! Failed to create expose region.\n"); + #endif + } + } +} + +void nxagentForwardRemoteExpose(void) +{ + if (REGION_NOTEMPTY(WindowTable[0] -> drawable.pScreen, nxagentRemoteExposeRegion)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentForwardRemoteExpose: Going to forward events.\n"); + #endif + + TraverseTree(WindowTable[0], nxagentClipAndSendExpose, (void *)nxagentRemoteExposeRegion); + + /* + * Now this region should be empty. + */ + + REGION_EMPTY(WindowTable[0] -> drawable.pScreen, nxagentRemoteExposeRegion); + } +} + +void nxagentAddRectToRemoteExposeRegion(BoxPtr rect) +{ + RegionRec exposeRegion; + + if (nxagentRemoteExposeRegion == NULL) + { + return; + } + + REGION_INIT(nxagentDefaultScreen, &exposeRegion, rect, 1); + + REGION_UNION(nxagentDefaultScreen, nxagentRemoteExposeRegion, + nxagentRemoteExposeRegion, &exposeRegion); + + REGION_UNINIT(nxagentDefaultScreen, &exposeRegion); +} + +int nxagentClipAndSendExpose(WindowPtr pWin, pointer ptr) +{ + RegionPtr exposeRgn; + RegionPtr remoteExposeRgn; + BoxRec box; + + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendExpose: Called.\n"); + #endif + + remoteExposeRgn = (RegionRec *) ptr; + + if (pWin -> drawable.class != InputOnly) + { + exposeRgn = REGION_CREATE(pWin -> drawable.pScreen, NULL, 1); + + box = *REGION_EXTENTS(pWin->drawable.pScreen, remoteExposeRgn); + + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendExpose: Root expose extents: [%d] [%d] [%d] [%d].\n", + box.x1, box.y1, box.x2, box.y2); + #endif + + box = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin -> clipList); + + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendExpose: Clip list extents for window at [%p]: [%d] [%d] [%d] [%d].\n", + pWin, box.x1, box.y1, box.x2, box.y2); + #endif + + REGION_INTERSECT(pWin -> drawable.pScreen, exposeRgn, remoteExposeRgn, &pWin -> clipList); + + if (REGION_NOTEMPTY(pWin -> drawable.pScreen, exposeRgn)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendExpose: Forwarding expose to window at [%p] pWin.\n", + pWin); + #endif + + /* + * The miWindowExposures() clears out the + * region parameters, so the subtract ope- + * ration must be done before calling it. + */ + + REGION_SUBTRACT(pWin -> drawable.pScreen, remoteExposeRgn, remoteExposeRgn, exposeRgn); + + miWindowExposures(pWin, exposeRgn, NullRegion); + } + + REGION_DESTROY(pWin -> drawable.pScreen, exposeRgn); + } + + if (REGION_NOTEMPTY(pWin -> drawable.pScreen, remoteExposeRgn)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendExpose: Region not empty. Walk children.\n"); + #endif + + return WT_WALKCHILDREN; + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentClipAndSendExpose: Region empty. Stop walking.\n"); + #endif + + return WT_STOPWALKING; + } +} + +int nxagentUserInput(void *p) +{ + int result = 0; + + /* + * This function is used as callback in + * the polling handler of agent in shadow + * mode. When inside the polling loop the + * handlers are never called, so we have + * to dispatch enqueued events to eventu- + * ally change the nxagentInputEvent sta- + * tus. + */ + + if (nxagentOption(Shadow) == 1 && + nxagentPendingEvents(nxagentDisplay) > 0) + { + nxagentDispatchEvents(NULL); + } + + if (nxagentInputEvent == 1) + { + nxagentInputEvent = 0; + + result = 1; + } + + /* + * The agent working in shadow mode synch- + * ronizes the remote X server even if a + * button/key is not released (i.e. when + * scrolling a long browser's page), in + * order to update the screen smoothly. + */ + + if (nxagentOption(Shadow) == 1) + { + return result; + } + + if (result == 0) + { + /* + * If there is at least one button/key down, + * we are receiving an input. This is not a + * condition to break a synchronization loop + * if there is enough bandwidth. + */ + + if (nxagentCongestion > 0 && + (inputInfo.pointer -> button -> buttonsDown > 0 || + nxagentKeyDown > 0)) + { + #ifdef TEST + fprintf(stderr, "nxagentUserInput: Buttons [%d] Keys [%d].\n", + inputInfo.pointer -> button -> buttonsDown, nxagentKeyDown); + #endif + + result = 1; + } + } + + return result; +} + +int nxagentHandleRRScreenChangeNotify(XEvent *X) +{ + XRRScreenChangeNotifyEvent *Xr; + + Xr = (XRRScreenChangeNotifyEvent *) X; + + nxagentResizeScreen(screenInfo.screens[DefaultScreen(nxagentDisplay)], Xr -> width, Xr -> height, + Xr -> mwidth, Xr -> mheight); + + nxagentShadowCreateMainWindow(screenInfo.screens[DefaultScreen(nxagentDisplay)], WindowTable[0], + Xr -> width, Xr -> height); + + nxagentShadowSetWindowsSize(); + + return 1; +} + +/* + * Returns true if there is any event waiting to + * be dispatched. This function is critical for + * the performance because it is called very, + * very often. It must also handle the case when + * the display is down. The display descriptor, + * in fact, may have been reused by some other + * client. + */ + +int nxagentPendingEvents(Display *dpy) +{ + if (_XGetIOError(dpy) != 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentPendingEvents: Returning error with display down.\n"); + #endif + + return -1; + } + else if (XQLength(dpy) > 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentPendingEvents: Returning true with [%d] events queued.\n", + XQLength(dpy)); + #endif + + return 1; + } + else + { + int result; + int readable; + + result = NXTransReadable(dpy -> fd, &readable); + + if (result == 0) + { + if (readable > 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentPendingEvents: Returning true with [%d] bytes readable.\n", + readable); + #endif + + return 1; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentPendingEvents: Returning false with [%d] bytes readable.\n", + readable); + #endif + + return 0; + } + + #ifdef TEST + fprintf(stderr, "nxagentPendingEvents: WARNING! Error detected on the X display.\n"); + #endif + + NXForceDisplayError(dpy); + + return -1; + } +} + +/* + * Blocks until an event becomes + * available. + */ + +int nxagentWaitEvents(Display *dpy, struct timeval *tm) +{ + XEvent ev; + + NXFlushDisplay(dpy, NXFlushLink); + + /* + * If the transport is not running we + * have to rely on Xlib to wait for an + * event. In this case the timeout is + * ignored. + */ + + if (NXTransRunning(NX_FD_ANY) == 1) + { + NXTransContinue(tm); + } + else + { + XPeekEvent(dpy, &ev); + } + + /* + * Check if we encountered a display + * error. If we did, wait for the + * time requested by the caller. + */ + + if (NXDisplayError(dpy) == 1) + { + if (tm != NULL) + { + usleep(tm -> tv_sec * 1000 * 1000 + + tm -> tv_usec); + } + + return -1; + } + + return 1; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.h b/nx-X11/programs/Xserver/hw/nxagent/Events.h new file mode 100644 index 000000000..4870f83e0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Events.h @@ -0,0 +1,223 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Events_H__ +#define __Events_H__ + +#include + +#define ProcessedExpose (LASTEvent + 1) +#define ProcessedNotify (LASTEvent + 2) + +#define EXPOSED_SIZE 256 + +enum HandleEventResult +{ + doNothing = 0, + doMinimize, + doCloseSession, + doStartKbd, + doSwitchFullscreen, + doViewportLeft, + doViewportUp, + doViewportRight, + doViewportDown, + doSwitchResizeMode, + doSwitchDeferMode +}; + +extern CARD32 nxagentLastEventTime; + +/* + * Manage incoming events. + */ + +typedef Bool (*PredicateFuncPtr)(Display*, XEvent*, XPointer); + +extern void nxagentDispatchEvents(PredicateFuncPtr); + +typedef int (*GetResourceFuncPtr)(Display*); + +int nxagentWaitForResource(GetResourceFuncPtr, PredicateFuncPtr); + +Bool nxagentCollectGrabPointerPredicate(Display *display, XEvent *X, XPointer ptr); + +int nxagentInputEventPredicate(Display *display, XEvent *event, XPointer parameter); + +/* + * Enable and disable notification of + * remote X server events. + */ + +extern void nxagentEnableKeyboardEvents(void); +extern void nxagentEnablePointerEvents(void); + +extern void nxagentDisableKeyboardEvents(void); +extern void nxagentDisablePointerEvents(void); + +/* + * Manage default event mask. + */ + +extern void nxagentInitDefaultEventMask(void); +extern void nxagentGetDefaultEventMask(Mask *mask_return); +extern void nxagentSetDefaultEventMask(Mask mask); +extern void nxagentGetEventMask(WindowPtr pWin, Mask *mask_return); + +/* + * Bring keyboard device in known state. It needs + * a round-trip so it only gets called if a pre- + * vious XKB event did not implicitly initialized + * the internal state. This is unlikely to happen. + */ + +extern int nxagentInitKeyboardState(void); + +/* + * Update the keyboard state according + * to focus and XKB events received + * from the remote X server. + */ + +extern int nxagentHandleKeyboardEvent(XEvent *X); + +/* + * Handle sync and karma messages and + * other notification event coming + * from proxy. + */ + +extern int nxagentHandleProxyEvent(XEvent *X); + +/* + * Other functions providing the ad-hoc + * handling of the remote X events. + */ + +extern int nxagentHandleExposeEvent(XEvent *X); +extern int nxagentHandleGraphicsExposeEvent(XEvent *X); +extern int nxagentHandleClientMessageEvent(XEvent *X, enum HandleEventResult*); +extern int nxagentHandlePropertyNotify(XEvent *X); +extern int nxagentHandleKeyPress(XEvent *X, enum HandleEventResult*); +extern int nxagentHandleReparentNotify(XEvent *X); +extern int nxagentHandleConfigureNotify(XEvent *X); + +/* + * Send a fake keystroke to the remote + * X server. + */ + +extern void nxagentSendFakeKey(int key); + +/* + * Called to manage grab of pointer and + * keyboard when running in fullscreen + * mode. + */ + +extern void nxagentGrabPointerAndKeyboard(XEvent *X); +extern void nxagentUngrabPointerAndKeyboard(XEvent *X); + +extern void nxagentDeactivatePointerGrab(void); + +/* + * Handle the selection property received + * in the event loop. + */ + +void nxagentCollectPropertyEvent(int resource); + +/* + * Synchronize expose events between agent and + * the real X server. + */ + +typedef struct _ExposuresRec +{ + WindowPtr pWindow; + RegionPtr localRegion; + RegionPtr remoteRegion; + Bool remoteRegionIsCompleted; + int serial; + int synchronize; + +} ExposuresRec; + +extern RegionPtr nxagentRemoteExposeRegion; + +typedef struct _ExposeQueue +{ + unsigned int start; + int length; + ExposuresRec exposures[EXPOSED_SIZE]; +} ExposeQueue; + +extern void nxagentSynchronizeExpose(void); +extern int nxagentLookupByWindow(WindowPtr pWin); +extern void nxagentUpdateExposeArray(void); + +extern ExposeQueue nxagentExposeQueue; + +/* + * Handle the split related notifications. + */ + +int nxagentWaitSplitEvent(int resource); + +void nxagentHandleNoSplitEvent(int resource); +void nxagentHandleStartSplitEvent(int resource); +void nxagentHandleCommitSplitEvent(int resource, int request, int position); +void nxagentHandleEndSplitEvent(int resource); +void nxagentHandleEmptySplitEvent(void); + +void nxagentInitRemoteExposeRegion(void); +void nxagentAddRectToRemoteExposeRegion(BoxPtr); + +extern int nxagentUserInput(void *p); + +/* +* We have to check these before launching the terminate + * dialog in rootless mode. + */ + +extern Bool nxagentLastWindowDestroyed; +extern Time nxagentLastWindowDestroyedTime; + +/* + * Set this flag if an user input event is received. + */ + +extern int nxagentInputEvent; + +/* + * Event-handling utilities. + */ + +Bool nxagentPendingEvents(Display *dpy); + +#define nxagentQueuedEvents(display) \ + XQLength((display)) + +#define nxagentReadEvents(display) \ + XEventsQueued((display), QueuedAfterReading) + +#define nxagentCheckEvents(display, event, predicate, argument) \ + XCheckIfEventNoFlush((display), (event), (predicate), (argument)) + +int nxagentWaitEvents(Display *, struct timeval *); + +#endif /* __Events_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Extensions.c b/nx-X11/programs/Xserver/hw/nxagent/Extensions.c new file mode 100644 index 000000000..f2954a3e9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Extensions.c @@ -0,0 +1,197 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "micmap.h" +#include "scrnintstr.h" +#include "../../randr/randrstr.h" + +#include "Agent.h" +#include "Display.h" +#include "Screen.h" +#include "Extensions.h" + +void GlxExtensionInit(void); +void GlxWrapInitVisuals(void *procPtr); + +#ifdef __DARWIN__ + +void DarwinHandleGUI(int argc, char *argv[]) +{ +} + +void DarwinGlxExtensionInit() +{ + GlxExtensionInit(); +} + +void DarwinGlxWrapInitVisuals(void *procPtr) +{ + GlxWrapInitVisuals(procPtr); +} + +#endif + +void nxagentInitGlxExtension(VisualPtr *visuals, DepthPtr *depths, + int *numVisuals, int *numDepths, int *rootDepth, + VisualID *defaultVisual) +{ + miInitVisualsProcPtr initVisuals; + + /* + * Initialize the visuals to use the GLX extension. + */ + + initVisuals = NULL; + + GlxWrapInitVisuals(&initVisuals); + + if (initVisuals(visuals, depths, numVisuals, numDepths, + rootDepth, defaultVisual, 0, 0, 0) == 0) + { + fprintf(stderr, "Warning: Failed to initialize the GLX extension.\n"); + } +} + +void nxagentInitRandRExtension(ScreenPtr pScreen) +{ + rrScrPrivPtr pRandRScrPriv; + + if (RRScreenInit(pScreen) == 0) + { + fprintf(stderr, "Warning: Failed to initialize the RandR extension.\n"); + } + + /* + * RRScreenInit sets these pointers to NULL, + * so requiring the server to set up its own + * replacements. + */ + + pRandRScrPriv = rrGetScrPriv(pScreen); + + pRandRScrPriv -> rrGetInfo = nxagentRandRGetInfo; + pRandRScrPriv -> rrSetConfig = nxagentRandRSetConfig; +} + +int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations) +{ + RRScreenSizePtr pSize; + + int width; + int height; + + int maxWidth; + int maxHeight; + + int w[] = {0, 160, 320, 640, 800, 1024, 0, 0}; + int h[] = {0, 120, 240, 480, 600, 768, 0, 0}; + + int i; + int nSizes; + + int mmWidth; + int mmHeight; + + /* + * Rotation is not supported. + */ + + *pRotations = RR_Rotate_0; + + /* + * Register all the supported sizes. The third + * parameter is the refresh rate. + */ + + maxWidth = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + maxHeight = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + + nSizes = sizeof w / sizeof(int); + + /* + * Add current and max sizes. + */ + + w[nSizes - 1] = pScreen -> width; + h[nSizes - 1] = pScreen -> height; + + w[nSizes - 2] = maxWidth; + h[nSizes - 2] = maxHeight; + + /* + * Compute default size. + */ + + w[0] = w[2]; + h[0] = h[2]; + + for (i = 3; i < nSizes - 1; i++) + { + if ((w[i] <= maxWidth * 3 / 4) && + (h[i] <= maxHeight * 3 / 4) && + (w[i] >= w[0]) && + (h[i] >= h[0])) + { + w[0] = w[i]; + h[0] = h[i]; + } + } + + for (i = 0; i < nSizes; i++) + { + width = w[i]; + height = h[i]; + + mmWidth = (width * 254 + monitorResolution * 5) / (monitorResolution * 10); + + if (mmWidth < 1) + { + mmWidth = 1; + } + + mmHeight = (height * 254 + monitorResolution * 5) / (monitorResolution * 10); + + if (mmHeight < 1) + { + mmHeight = 1; + } + + pSize = RRRegisterSize(pScreen, width, height, mmWidth, mmHeight); + + if (pSize == NULL) + { + return 0; + } + + RRRegisterRate (pScreen, pSize, 60); + } + + RRSetCurrentConfig(pScreen, RR_Rotate_0, 60, pSize); + + return 1; +} + +int nxagentRandRSetConfig(ScreenPtr pScreen, Rotation rotation, + int rate, RRScreenSizePtr pSize) +{ + /* + * Whatever size is OK for us. + */ + + return nxagentResizeScreen(pScreen, pSize -> width, pSize -> height, + pSize -> mmWidth, pSize -> mmHeight); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Extensions.h b/nx-X11/programs/Xserver/hw/nxagent/Extensions.h new file mode 100644 index 000000000..f76229867 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Extensions.h @@ -0,0 +1,35 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * Initialize the additional extensions. + */ + +void nxagentInitGlxExtension(VisualPtr *visuals, DepthPtr *depths, + int *numVisuals, int *numDepths, int *rootDepth, + VisualID *defaultVisual); + +void nxagentInitRandRExtension(ScreenPtr pScreen); + +/* + * Basic interface to the RandR extension. + */ + +int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations); + +int nxagentRandRSetConfig(ScreenPtr pScreen, Rotation rotation, + int rate, RRScreenSizePtr pSize); diff --git a/nx-X11/programs/Xserver/hw/nxagent/Font.c b/nx-X11/programs/Xserver/hw/nxagent/Font.c new file mode 100644 index 000000000..ff968bcc5 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Font.c @@ -0,0 +1,1690 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "scrnintstr.h" +#include "dixstruct.h" +#include "../../../../include/fonts/font.h" +#include "fontstruct.h" +#include "misc.h" +#include "miscstruct.h" +#include "opaque.h" + +#include "Agent.h" + +#include "Display.h" +#include "Font.h" +#include "Error.h" + +#include +#include +#include "resource.h" +#include "Reconnect.h" + +#include "Args.h" + +#include "NXlib.h" +#include "NXalert.h" + +#include +#include + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#define NXAGENT_DEFAULT_FONT_DIR "/usr/X11R6/lib/X11/fonts" +#define NXAGENT_ALTERNATE_FONT_DIR "/usr/share/X11/fonts" +#define NXAGENT_ALTERNATE_FONT_DIR_2 "/usr/share/fonts/X11" +#define NXAGENT_ALTERNATE_FONT_DIR_3 "/usr/share/fonts" + +#define NXAGENT_DEFAULT_FONT_PATH \ +"/usr/X11R6/lib/X11/fonts/misc/,/usr/X11R6/lib/X11/fonts/Speedo/,\ +/usr/X11R6/lib/X11/fonts/Type1/,/usr/X11R6/lib/X11/fonts/75dpi/,\ +/usr/X11R6/lib/X11/fonts/100dpi/,/usr/X11R6/lib/X11/fonts/TTF/" + +#define NXAGENT_ALTERNATE_FONT_PATH \ +"/usr/share/X11/fonts/misc/,/usr/share/X11/fonts/Speedo/,\ +/usr/share/X11/fonts/Type1/,/usr/share/X11/fonts/75dpi/,\ +/usr/share/X11/fonts/100dpi/,/usr/share/X11/fonts/TTF/" + +#define NXAGENT_ALTERNATE_FONT_PATH_2 \ +"/usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Speedo/,\ +/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,\ +/usr/share/fonts/X11/100dpi/,/usr/share/fonts/X11/TTF/" + +#define NXAGENT_ALTERNATE_FONT_PATH_3 \ +"/usr/share/fonts/misc/,/usr/share/fonts/Speedo/,\ +/usr/share/fonts/Type1/,/usr/share/fonts/75dpi/,\ +/usr/share/fonts/100dpi/,/usr/share/fonts/TTF/" + +#undef NXAGENT_FONTCACHE_DEBUG +#undef NXAGENT_RECONNECT_FONT_DEBUG +#undef NXAGENT_FONTMATCH_DEBUG + +#define FIELDS 14 + +static int reconnectFlexibility; + +static void nxagentCleanCacheAfterReconnect(void); +static void nxagentFontReconnect(FontPtr, XID, pointer); +static XFontStruct *nxagentLoadBestQueryFont(Display* dpy, char *fontName, FontPtr pFont); +static XFontStruct *nxagentLoadQueryFont(register Display *dpy , char *fontName , FontPtr pFont); +int nxagentFreeFont(XFontStruct *fs); +static Bool nxagentGetFontServerPath(char * fontServerPath); + +RESTYPE RT_NX_FONT; + +#ifdef NXAGENT_RECONNECT_FONT_DEBUG +static void printFontCacheDump(char*); +#endif + +typedef struct _nxagentFontRec +{ + char *name; + int status; +} nxagentFontRec, *nxagentFontRecPtr; + +typedef struct _nxagentFontList +{ + nxagentFontRecPtr *list; + int length; + int listSize; +} nxagentFontList, *nxagentFontListPtr; + +nxagentFontList nxagentRemoteFontList = {NULL, (int)0, (int)0}; + +int nxagentFontPrivateIndex; + +typedef struct _nxCacheFontEntry +{ + Atom atom; + XFontStruct *font_struct; + char *name; +} nxCacheFontEntryRec, *nxCacheFontEntryRecPtr; + +static struct _nxagentFontCache +{ + nxCacheFontEntryRecPtr *entry; + int index; + int size; +} nxagentFontCache = { NULL, (int) 0, (int) 0 }; + +#define CACHE_ENTRY_PTR (nxagentFontCache.entry) +#define CACHE_INDEX (nxagentFontCache.index) +#define CACHE_SIZE (nxagentFontCache.size) +#define CACHE_ENTRY(A) (CACHE_ENTRY_PTR[A]) +#define CACHE_FSTRUCT(A) (CACHE_ENTRY(A) -> font_struct) +#define CACHE_NAME(A) (CACHE_ENTRY(A) -> name) +#define CACHE_ATOM(A) (CACHE_ENTRY(A) -> atom) + +static struct _nxagentFailedToReconnectFonts +{ + FontPtr *font; + XID *id; + int size; + int index; +} nxagentFailedToReconnectFonts = {NULL, NULL, 0, 0}; + +/* + * This is used if nxagentFullGeneration is true + * in CloseDisplay(). + */ + +void nxagentFreeFontCache(void) +{ + int i; + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: Freeing nxagent font cache\n"); + #endif + + if (CACHE_INDEX == 0) + return; + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: Freeing nxagent font cache, there are [%d] entries.\n", CACHE_INDEX); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: Freeing nxagent font cache entry [%d] entry pointer is [%p], name [%s]\n", + i, CACHE_ENTRY(i), CACHE_NAME(i)); + #endif + + if (CACHE_FSTRUCT(i)) + { + nxagentFreeFont(CACHE_FSTRUCT(i)); + } + + xfree(CACHE_NAME(i)); + xfree(CACHE_ENTRY(i)); + } + + xfree(CACHE_ENTRY_PTR); + CACHE_ENTRY_PTR = NULL; + CACHE_INDEX = 0; + CACHE_SIZE = 0; + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagent font cache fully freed\n"); + #endif + + return; +} + +void nxagentListRemoteFonts(const char *searchPattern, const int maxNames) +{ + int i, q, p; + + char **xList; + int xLen = 0; + + const char *patterns[] = {"*", "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"}; + int patternsQt = 2; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return; + } + + /* + * Avoid querying again the remote + * fonts. + */ + + if (nxagentRemoteFontList.length > 0) + { + return; + } + + /* + * We can't retrieve the full remote font + * list with a single query, because the + * number of dashes in the pattern acts as + * a rule to select how to search for the + * font names, so the pattern '*' is useful + * to retrive the font aliases, while the + * other one will select the 'real' fonts. + */ + + for (p = 0; p < patternsQt; p++) + { + xList = XListFonts(nxagentDisplay, patterns[p], maxNames, &xLen); + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxagentListRemoteFonts: NXagent remote list [%s] has %d elements.\n", patterns[p], xLen); + #endif + + /* + * Add the ListFont request pattern to the list with + * the last requested maxnames. + */ + + nxagentListRemoteAddName(searchPattern, maxNames); + + for (i = 0; i < xLen; i++) + { + q = 1; + + nxagentListRemoteAddName(xList[i], q); + } + + XFreeFontNames(xList); + } + + #ifdef NXAGENT_FONTMATCH_DEBUG + + fprintf(stderr, "nxagentListRemoteFonts: Printing remote font list.\n"); + + for (i = 0; i < nxagentRemoteFontList.length; i++) + { + fprintf(stderr, "Font# %d, \"%s\"\n", i, nxagentRemoteFontList.list[i]->name); + } + + fprintf(stderr, "nxagentListRemoteFonts: End of list\n"); + + #endif +} + +void nxagentListRemoteAddName(const char *name, int status) +{ + int pos; + + if (nxagentFontFind(name, &pos)) + { + if (nxagentRemoteFontList.list[pos]->status < status) + { + nxagentRemoteFontList.list[pos]->status = status; + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Font# %d, [%s] change status to %s\n", + pos, nxagentRemoteFontList.list[pos]->name,nxagentRemoteFontList.list[pos]->status?"OK":"deleted"); + #endif + } + return; + } + + if (nxagentRemoteFontList.length == nxagentRemoteFontList.listSize) + { + nxagentRemoteFontList.list = xrealloc(nxagentRemoteFontList.list, sizeof(nxagentFontRecPtr) + * (nxagentRemoteFontList.listSize + 1000)); + + if (nxagentRemoteFontList.list == NULL) + { + FatalError("Font: remote list memory re-allocation failed!.\n"); + } + + nxagentRemoteFontList.listSize += 1000; + } + + if (pos < nxagentRemoteFontList.length) + { + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Going to move list from %p to %p len = %d!.\n", + &nxagentRemoteFontList.list[pos], &nxagentRemoteFontList.list[pos+1], + (nxagentRemoteFontList.length - pos) * sizeof(nxagentFontRecPtr)); + #endif + + memmove(&nxagentRemoteFontList.list[pos+1], + &nxagentRemoteFontList.list[pos], + (nxagentRemoteFontList.length - pos) * sizeof(nxagentFontRecPtr)); + } + + if ((nxagentRemoteFontList.list[pos] = xalloc(sizeof(nxagentFontRec)))) + { + nxagentRemoteFontList.list[pos]->name = xalloc(strlen(name) +1); + if (nxagentRemoteFontList.list[pos]->name == NULL) + { + fprintf(stderr, "Font: remote list name memory allocation failed!.\n"); + return; + } + } + else + { + fprintf(stderr, "Font: remote list record memory allocation failed!.\n"); + return; + } + strcpy(nxagentRemoteFontList.list[pos]->name,name); + nxagentRemoteFontList.list[pos]->status = status; + nxagentRemoteFontList.length++; + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: remote font list added [%s] in position [%d] as %s !.\n", + name, pos, status ? "OK" : "deleted"); + fprintf(stderr, "Font: remote font list total len is [%d] Size is [%d] !.\n", + nxagentRemoteFontList.length, nxagentRemoteFontList.listSize); + #endif +} + +static void nxagentFreeRemoteFontList(nxagentFontList *listRec) +{ + int l; + + for (l = 0; l < listRec -> length; l++) + { + if (listRec -> list[l]) + { + xfree(listRec -> list[l] -> name); + listRec -> list[l] -> name = NULL; + + xfree(listRec -> list[l]); + listRec -> list[l] = NULL; + } + } + + listRec -> length = listRec -> listSize = 0; + + free(listRec -> list); + listRec -> list = NULL; + + return; +} + +Bool nxagentFontFind(const char *name, int *pos) +{ + int low,high,res,iter,lpos; + + if (!nxagentRemoteFontList.length) + { + *pos=0; + return False; + } + low = 0; + high = nxagentRemoteFontList.length - 1; + iter = 0; + res = 1; + lpos = nxagentRemoteFontList.length; + while (low <= high) + { + *pos = (high + low)/2; + iter ++; + res = strcasecmp(nxagentRemoteFontList.list[*pos]->name,name); + if (res > 0) + { + high = *pos - 1; + lpos = *pos; + continue; + } + else if (res < 0) + { + low = *pos + 1; + lpos = low; + continue; + } + break; + } + *pos = (res == 0)?*pos:lpos; + + #ifdef NXAGENT_FONTMATCH_DEBUG + if (res == 0) + fprintf(stderr, "Font: font found in %d iterations in pos = %d\n", iter, *pos); + else + fprintf(stderr, "Font: not font found in %d iterations insertion pos is = %d\n", iter, *pos); + #endif + + return (res == 0); + +} + +Bool nxagentFontLookUp(const char *name) +{ + int i; + if (name) + if (!strlen(name)) + return 0; + if (nxagentFontFind(name, &i)) + return (nxagentRemoteFontList.list[i]->status > 0); + else + return 0; +} + +Bool nxagentRealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + pointer priv; + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + char *origName = (char*) pScreen; + + FontSetPrivate(pFont, nxagentFontPrivateIndex, NULL); + + if (requestingClient && XpClientIsPrintClient(requestingClient, NULL)) + return True; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if ((Atom)props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return False; + + name = (char *)NameForAtom(value_atom); + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentRealizeFont, realizing font: %s\n", validateString(name)); + fprintf(stderr, " atom: %ld\n", value_atom); + fprintf(stderr, "Font: Cache dump:\n"); + for (i = 0; i < CACHE_INDEX; i++) + { + fprintf(stderr, "nxagentFontCache.entry[%d]->name: %s font_struct at %p\n", + i, CACHE_NAME(i), CACHE_FSTRUCT(i)); + } + #endif + + if (!name) return False; + + if ((strcasecmp(origName, name) != 0) && !strchr(origName,'*')) + { + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Changing font name to realize from [%s] to [%s]\n", + validateString(name), origName); + #endif + + name = origName; + } + + priv = (pointer)xalloc(sizeof(nxagentPrivFont)); + FontSetPrivate(pFont, nxagentFontPrivateIndex, priv); + + nxagentFontPriv(pFont) -> mirrorID = 0; + + for (i = 0; i < nxagentFontCache.index; i++) + { +/* if (value_atom == CACHE_ATOM(i))*/ + if (strcasecmp(CACHE_NAME(i), name) == 0) + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentFontCache hit [%s] = [%s]!\n", CACHE_NAME(i), validateString(name)); + #endif + + break; + } + } + + if (i < CACHE_INDEX) + { + nxagentFontPriv(pFont)->font_struct = CACHE_FSTRUCT(i); + strcpy(nxagentFontPriv(pFont)->fontName, name); + } + else + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentFontCache fail.\n"); + #endif + + if (CACHE_INDEX == CACHE_SIZE) + { + CACHE_ENTRY_PTR = xrealloc(CACHE_ENTRY_PTR, sizeof(nxCacheFontEntryRecPtr) * (CACHE_SIZE + 100)); + + if (CACHE_ENTRY_PTR == NULL) + { + FatalError("Font: Cache list memory re-allocation failed.\n"); + } + + CACHE_SIZE += 100; + } + + CACHE_ENTRY(CACHE_INDEX) = xalloc(sizeof(nxCacheFontEntryRec)); + + if (CACHE_ENTRY(CACHE_INDEX) == NULL) + { + return False; + } + + CACHE_NAME(CACHE_INDEX) = xalloc(strlen(name) + 1); + + if (CACHE_NAME(CACHE_INDEX) == NULL) + { + return False; + } + + #ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Font: Going to realize font [%s],[%s] on real X server.\n", validateString(name), origName); + #endif + + if (nxagentRemoteFontList.length == 0 && (NXDisplayError(nxagentDisplay) == 0)) + { + nxagentListRemoteFonts("*", nxagentMaxFontNames); + } + + nxagentFontPriv(pFont)->font_struct = nxagentLoadQueryFont(nxagentDisplay, name, pFont); + strcpy(nxagentFontPriv(pFont)->fontName, name); + if (nxagentFontPriv(pFont)->font_struct != NULL) + { + CACHE_ATOM(i) = value_atom; + strcpy(CACHE_NAME(i), name); + CACHE_FSTRUCT(i) = nxagentFontPriv(pFont)->font_struct; + CACHE_INDEX++; + + nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index); + AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont); + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "Font: nxagentFontCache adds font [%s] in pos. [%d].\n", + validateString(name), CACHE_INDEX - 1); + #endif + } + } + + #ifdef NXAGENT_FONTMATCH_DEBUG + + if (nxagentFontPriv(pFont)->font_struct == NULL) + { + if (nxagentFontLookUp(name) == False) + { + fprintf(stderr, "Font: nxagentRealizeFont failed with font Font=%s, not in our remote list\n", + validateString(name)); + } + else + { + fprintf(stderr, "Font: nxagentRealizeFont failed with font Font=%s but the font is in our remote list\n", + validateString(name)); + } + } + else + fprintf(stderr, "Font: nxagentRealizeFont OK realizing font Font=%s\n", + validateString(name)); + + #endif + + return (nxagentFontPriv(pFont)->font_struct != NULL); +} + +Bool nxagentUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + if (nxagentFontPriv(pFont)) + { + if (NXDisplayError(nxagentDisplay) == 0) + { + if (nxagentFontStruct(pFont)) + { + int i; + + for (i = 0; i < CACHE_INDEX; i++) + { + if (CACHE_FSTRUCT(i) == nxagentFontStruct(pFont)) + { + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "nxagentUnrealizeFont: Not freeing the font in cache.\n"); + #endif + + break; + } + } + + if (i == CACHE_INDEX) + { + /* + * This font is not in the cache. + */ + + #ifdef NXAGENT_FONTCACHE_DEBUG + fprintf(stderr, "nxagentUnrealizeFont: Freeing font not found in cache '%d'\n", + CACHE_ATOM(i)); + #endif + + XFreeFont(nxagentDisplay, nxagentFontStruct(pFont)); + } + } + } + + if (nxagentFontPriv(pFont) -> mirrorID) + FreeResource(nxagentFontPriv(pFont) -> mirrorID, RT_NONE); + + xfree(nxagentFontPriv(pFont)); + FontSetPrivate(pFont, nxagentFontPrivateIndex, NULL); + } + + return True; +} + +int nxagentDestroyNewFontResourceType(pointer p, XID id) +{ + #ifdef TEST + fprintf(stderr, "nxagentDestroyNewFontResourceType: Destroying mirror id [%ld] for font at [%p].\n", + nxagentFontPriv((FontPtr) p) -> mirrorID, (void *) p); + #endif + +/* +FIXME: It happens that this resource had been already + destroied. We should verify if the same font is + assigned both to the server client and another + client. We had a crash when freeing server client + resources. +*/ + if (nxagentFontPriv((FontPtr) p) != NULL) + { + nxagentFontPriv((FontPtr) p) -> mirrorID = None; + } + + return 1; +} + +static XFontStruct *nxagentLoadBestQueryFont(Display* dpy, char *fontName, FontPtr pFont) +{ + XFontStruct *fontStruct; + + char *substFontBuf; + + /* X Logical Font Description Conventions + * require 14 fields in the font names. + * + */ + char *searchFields[FIELDS+1]; + char *fontNameFields[FIELDS+1]; + int i; + int j; + int numSearchFields = 0; + int numFontFields = 0; + int weight = 0; + int tempWeight = 1; + int fieldOrder[14] = { 4, /* Slant */ + 11, /* Spacing */ + 12, /* Width info */ + 13, /* Charset */ + 14, /* Language */ + 7, /* Height */ + 6, /* Add-style */ + 3, /* Weight */ + 2, /* Name */ + 1, /* Foundry */ + 9, /* DPI_x */ + 5, /* Set-width */ + 8, /* Point size */ + 10 /* DPI_y */ + }; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentLoadBestQueryFont: Searching font '%s' .\n", fontName); + #endif + + substFontBuf = (char *) xalloc(sizeof(char) * 512); + + + numFontFields = nxagentSplitString(fontName, fontNameFields, FIELDS, "-"); + + memcpy(substFontBuf, "fixed\0", strlen("fixed") + 1); + + if (numFontFields <= FIELDS) + { + #ifdef WARNING + if (nxagentVerbose == 1) + { + fprintf(stderr, "nxagentLoadBestQueryFont: WARNING! Font name in non standard format. \n"); + } + #endif + } + else + { + for (i = 1 ; i < nxagentRemoteFontList.length ; i++) + { + numSearchFields = nxagentSplitString(nxagentRemoteFontList.list[i]->name, searchFields, FIELDS+1, "-"); + + + /* The following code attemps to find an accurate approximation + * of the missing font. The current candidate and the missing font are + * compared on the 14 fields of the X Logical Font Description Convention. + * The selection is performed by the analysis of the matching fields, + * shifting left the value of the Weight variable on the right matches + * and shifting right the value of the Weight on the wrong ones; + * due a probability of overmuch right shifting, the starting weight is set + * to a high value. At the end of matching the selected font is the one + * with the bigger final Weight. The shift operation has been used instead + * of other operation for a performance issue. + * In some check the shift is performed by more than one position, because + * of the relevance of the field; for example a correct slant or a matching + * charset is more relevant than the size. + */ + + if (numSearchFields > FIELDS) + { + + tempWeight = 0; + + for (j = 0; j < FIELDS; j++) + { + if (strcasecmp(searchFields[fieldOrder[j]], fontNameFields[fieldOrder[j]]) == 0 || + strcmp(searchFields[fieldOrder[j]], "") == 0 || + strcmp(fontNameFields[fieldOrder[j]], "") != 0 || + strcmp(searchFields[fieldOrder[j]], "*") == 0 || + strcmp(fontNameFields[fieldOrder[j]], "*") == 0) + { + tempWeight ++; + } + + tempWeight <<= 1; + } + + } + + if (tempWeight > weight) + { + /* Found more accurate font */ + + weight = tempWeight; + memcpy(substFontBuf, nxagentRemoteFontList.list[i]->name, strlen(nxagentRemoteFontList.list[i]->name)); + substFontBuf[strlen(nxagentRemoteFontList.list[i]->name)] = '\0'; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentLoadBestQueryFont: Weight '%d' of more accurate font '%s' .\n", weight, substFontBuf); + #endif + } + } + } + + #ifdef WARNING + if (nxagentVerbose == 1) + { + fprintf(stderr, "nxagentLoadBestQueryFont: WARNING! Failed to load font '%s'. Replacing with '%s'.\n", + fontName, substFontBuf); + } + #endif + + fontStruct = nxagentLoadQueryFont(dpy, substFontBuf, pFont); + + free (substFontBuf); + + return fontStruct; +} + +static void nxagentFontDisconnect(FontPtr pFont, XID param1, pointer param2) +{ + nxagentPrivFont *privFont; + Bool *pBool = (Bool*)param2; + int i; + + if (pFont == NULL || !*pBool) + return; + + privFont = nxagentFontPriv(pFont); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontDisconnect: pFont %p, XID %lx\n", + (void *) pFont, privFont -> font_struct ? nxagentFont(pFont) : 0); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontDisconnect: font %s found in cache at position %d\n", + privFont -> fontName, i); + #endif + + privFont -> font_struct = NULL; + return; + } + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontDisconnect: WARNING font %s not found in cache freeing it now\n", + privFont -> fontName); + #endif + + if (privFont -> font_struct) + { + XFreeFont(nxagentDisplay, privFont -> font_struct); + privFont -> font_struct = NULL; + } +} + +static void nxagentCollectFailedFont(FontPtr fpt, XID id) +{ + + if (nxagentFailedToReconnectFonts.font == NULL) + { + nxagentFailedToReconnectFonts.size = 8; + + nxagentFailedToReconnectFonts.font = malloc(nxagentFailedToReconnectFonts.size * + sizeof(FontPtr)); + + nxagentFailedToReconnectFonts.id = malloc(nxagentFailedToReconnectFonts.size * sizeof(XID)); + + if (nxagentFailedToReconnectFonts.font == NULL || nxagentFailedToReconnectFonts.id == NULL) + { + FatalError("Font: font not reconnected memory allocation failed!.\n"); + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentCollectFailedFont: allocated [%d] bytes.\n", + 8 * (sizeof(FontPtr)+ sizeof(XID))); + #endif + } + else if (nxagentFailedToReconnectFonts.index == nxagentFailedToReconnectFonts.size - 1) + { + nxagentFailedToReconnectFonts.size *= 2; + + nxagentFailedToReconnectFonts.font = realloc(nxagentFailedToReconnectFonts.font, + nxagentFailedToReconnectFonts.size * + sizeof(FontPtr)); + + nxagentFailedToReconnectFonts.id = realloc(nxagentFailedToReconnectFonts.id, + nxagentFailedToReconnectFonts.size * + sizeof(XID)); + + if (nxagentFailedToReconnectFonts.font == NULL || nxagentFailedToReconnectFonts.id == NULL) + { + FatalError("Font: font not reconnected memory re-allocation failed!.\n"); + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr,"nxagentCollectFailedFont: reallocated memory.\n "); + #endif + } + + nxagentFailedToReconnectFonts.font[nxagentFailedToReconnectFonts.index] = fpt; + + nxagentFailedToReconnectFonts.id[nxagentFailedToReconnectFonts.index] = id; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentCollectFailedFont: font not reconnected at [%p], " + "put in nxagentFailedToReconnectFonts.font[%d] = [%p], with XID = [%lu].\n", + (void*) fpt, nxagentFailedToReconnectFonts.index, + (void *)nxagentFailedToReconnectFonts.font[nxagentFailedToReconnectFonts.index], + nxagentFailedToReconnectFonts.id[nxagentFailedToReconnectFonts.index]); + #endif + + nxagentFailedToReconnectFonts.index++; +} + +static void nxagentFontReconnect(FontPtr pFont, XID param1, pointer param2) +{ + int i; + nxagentPrivFont *privFont; + Bool *pBool = (Bool*)param2; + + if (pFont == NULL) + return; + + privFont = nxagentFontPriv(pFont); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontReconnect: pFont %p - XID %lx - name %s\n", + (void*) pFont, (privFont -> font_struct) ? nxagentFont(pFont) : 0, + privFont -> fontName); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tfound in cache"); + #endif + + if (!CACHE_FSTRUCT(i)) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, " --- font struct not valid\n"); + #endif + + break; + } + + nxagentFontStruct(pFont) = CACHE_FSTRUCT(i); + + return; + } + } + + if (i == CACHE_INDEX) + { + FatalError("nxagentFontReconnect: font not found in cache."); + } + + privFont -> font_struct = nxagentLoadQueryFont(nxagentDisplay, privFont -> fontName, pFont); + + if ((privFont -> font_struct == NULL) && reconnectFlexibility) + { + privFont -> font_struct = nxagentLoadBestQueryFont(nxagentDisplay, privFont -> fontName, pFont); + } + + if (privFont->font_struct != NULL) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tXID %lx\n", privFont -> font_struct -> fid); + #endif + + CACHE_FSTRUCT(i) = privFont -> font_struct; + } + else + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontReconnect: failed\n"); + #endif + + nxagentCollectFailedFont(pFont, param1); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFontReconnect: reconnection of font [%s] failed.\n", + privFont -> fontName); + #endif + + nxagentSetReconnectError(FAILED_RESUME_FONTS_ALERT, + "Couldn't restore the font '%s'", privFont -> fontName); + + *pBool = False; + } + + return; +} + +static void nxagentFreeCacheBeforeReconnect(void) +{ + int i; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + printFontCacheDump("nxagentFreeCacheBeforeReconnect"); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (CACHE_FSTRUCT(i)) + { + nxagentFreeFont(CACHE_FSTRUCT(i)); + CACHE_FSTRUCT(i) = NULL; + } + } +} + +static void nxagentCleanCacheAfterReconnect(void) +{ + int i, j; + int real_size = CACHE_INDEX; + nxCacheFontEntryRecPtr swapEntryPtr; + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + printFontCacheDump("nxagentCleanCacheAfterReconnect"); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if(CACHE_FSTRUCT(i) == NULL) + { + XFree(CACHE_NAME(i)); + real_size--; + } + } + + for (i = 0; i < real_size; i++) + { + /* Find - first bad occurrence if exist. */ + while ((i < real_size) && CACHE_FSTRUCT(i)) i++; + + /* Really nothing more to do. */ + if (i == real_size) + break; + + /* + * Find - first good occurrence (moving backward from right end) entry in + * order to replace the bad one. + */ + for (j = CACHE_INDEX - 1; CACHE_FSTRUCT(j) == NULL; j--); + + /* + * Now we can swap the two entry + * and reduce the Cache index + */ + swapEntryPtr = CACHE_ENTRY(i); + CACHE_ENTRY(i) = CACHE_ENTRY(j); + CACHE_ENTRY(j) = swapEntryPtr; + } + + CACHE_INDEX = real_size; +} + +#ifdef NXAGENT_RECONNECT_FONT_DEBUG +static void printFontCacheDump(char* msg) +{ + int i; + + fprintf(stderr, "%s - begin -\n", msg); + + for (i = 0; i < CACHE_INDEX; i++) + { + if (CACHE_FSTRUCT(i)) + { + fprintf(stderr, "\tXID %lx - %s\n", CACHE_FSTRUCT(i) -> fid, CACHE_NAME(i)); + } + else + { + fprintf(stderr, "\tdestroyed - %s\n", CACHE_NAME(i)); + } + } + fprintf(stderr, "%s - end -\n", msg); +} +#endif + +Bool nxagentReconnectAllFonts(void *p0) +{ + int cid; + Bool fontSuccess = True; + + reconnectFlexibility = *((int *) p0); + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_FONT_DEBUG) + fprintf(stderr, "nxagentReconnectAllFonts\n"); + #endif + + /* + * The resource type RT_NX_FONT is created on the + * server client only, so we can avoid to loop + * through all the clients. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_FONT, + (FindResType) nxagentFontReconnect, &fontSuccess); + + for (cid = 0; cid < MAXCLIENTS; cid++) + { + if (clients[cid]) + { + FindClientResourcesByType(clients[cid], RT_FONT, + (FindResType) nxagentFontReconnect, &fontSuccess); + } + } + + if (fontSuccess) + { + nxagentCleanCacheAfterReconnect(); + } + + return fontSuccess; +} + +static void nxagentFailedFontReconnect(FontPtr pFont, XID param1, pointer param2) +{ + int i; + nxagentPrivFont *privFont; + Bool *pBool = (Bool*)param2; + + if (pFont == NULL) + return; + + privFont = nxagentFontPriv(pFont); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFailedFontReconnect: pFont %p - XID %lx - name %s\n", + (void*) pFont, (privFont -> font_struct) ? nxagentFont(pFont) : 0, + privFont -> fontName); + #endif + + for (i = 0; i < CACHE_INDEX; i++) + { + if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tfound in cache"); + #endif + + if (!CACHE_FSTRUCT(i)) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, " --- font struct not valid\n"); + #endif + + break; + } + + nxagentFontStruct(pFont) = CACHE_FSTRUCT(i); + + return; + } + } + + if (i == CACHE_INDEX) + { + FatalError("nxagentFailedFontReconnect: font not found in cache."); + } + + privFont -> font_struct = nxagentLoadQueryFont(nxagentDisplay, privFont -> fontName, pFont); + + if (privFont -> font_struct == NULL) + { + privFont -> font_struct = nxagentLoadBestQueryFont(nxagentDisplay, privFont -> fontName, pFont); + } + + if (privFont->font_struct != NULL) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "\tXID %lx\n", privFont -> font_struct -> fid); + #endif + + CACHE_FSTRUCT(i) = privFont -> font_struct; + } + else + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFailedFontReconnect: failed\n"); + #endif + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentFailedFontReconnect: reconnection of font [%s] failed.\n", + privFont -> fontName); + #endif + + nxagentSetReconnectError(FAILED_RESUME_FONTS_ALERT, + "Couldn't restore the font '%s'", privFont -> fontName); + + *pBool = False; + } + + return; +} + +static void nxagentFreeFailedToReconnectFonts() +{ + if (nxagentFailedToReconnectFonts.font != NULL) + { + free(nxagentFailedToReconnectFonts.font); + nxagentFailedToReconnectFonts.font = NULL; + } + + if (nxagentFailedToReconnectFonts.id != NULL) + { + free(nxagentFailedToReconnectFonts.id); + nxagentFailedToReconnectFonts.id = NULL; + } + + nxagentFailedToReconnectFonts.size = 0; + nxagentFailedToReconnectFonts.index = 0; +} + +Bool nxagentReconnectFailedFonts(void *p0) +{ + int i; + int attempt = 1; + const int maxAttempt = 5; + + char **fontPaths, **localFontPaths, **newFontPaths; + char fontServerPath[256]; + int nPaths = 0; + + Bool repeat = True; + Bool fontSuccess = True; + + reconnectFlexibility = *((int *) p0); + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentReconnectFailedFonts: \n"); + #endif + + if (nxagentGetFontServerPath(fontServerPath) == False) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectFailedFonts: WARNING! " + "Font server tunneling not retrieved.\n"); + #endif + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentReconnectFailedFonts: font server path [%s]\n", fontServerPath); + #endif + + fontPaths = XGetFontPath(nxagentDisplay, &nPaths); + + if ((newFontPaths = malloc((nPaths + 1) * sizeof(char *))) == NULL) + { + FatalError("nxagentReconnectFailedFonts: malloc failed."); + } + + memcpy(newFontPaths, fontPaths, nPaths * sizeof(char*)); + + localFontPaths = newFontPaths; + localFontPaths += nPaths; + *localFontPaths = fontServerPath; + + while(repeat) + { + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentReconnectFailedFonts: attempt [%d].\n", attempt); + #endif + + repeat = False; + + XSetFontPath(nxagentDisplay, newFontPaths, nPaths + 1); + nxagentFreeRemoteFontList(&nxagentRemoteFontList); + nxagentListRemoteFonts("*", nxagentMaxFontNames); + + for(i = 0; i < nxagentFailedToReconnectFonts.index; i++) + { + fontSuccess = True; + + if(nxagentFailedToReconnectFonts.font[i]) + { + nxagentFailedFontReconnect(nxagentFailedToReconnectFonts.font[i], + nxagentFailedToReconnectFonts.id[i], + &fontSuccess); + + if (fontSuccess) + { + nxagentFailedToReconnectFonts.font[i] = NULL; + } + else + { + repeat = True; + } + + } + } + + attempt++; + + if (attempt > maxAttempt) + { + nxagentFreeFailedToReconnectFonts(); + + XSetFontPath(nxagentDisplay, fontPaths, nPaths); + nxagentFreeRemoteFontList(&nxagentRemoteFontList); + nxagentListRemoteFonts("*", nxagentMaxFontNames); + + XFreeFontPath(fontPaths); + free(newFontPaths); + + return False; + } + } + + nxagentFreeFailedToReconnectFonts(); + + XSetFontPath(nxagentDisplay, fontPaths, nPaths); + + XFreeFontPath(fontPaths); + free(newFontPaths); + + nxagentCleanCacheAfterReconnect(); + + return True; +} + +Bool nxagentDisconnectAllFonts() +{ + int cid; + Bool fontSuccess = True; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_FONT_DEBUG) + fprintf(stderr, "nxagentDisconnectAllFonts\n"); + #endif + + nxagentFreeRemoteFontList(&nxagentRemoteFontList); + nxagentFreeCacheBeforeReconnect(); + + /* + * The resource type RT_NX_FONT is created on the + * server client only, so we can avoid to loop + * through all the clients. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_FONT, + (FindResType) nxagentFontDisconnect, &fontSuccess); + + for(cid = 0; cid < MAXCLIENTS; cid++) + { + if( clients[cid] && fontSuccess ) + { + FindClientResourcesByType(clients[cid], RT_FONT, + (FindResType) nxagentFontDisconnect, &fontSuccess); + } + } + + return True; +} + +static Bool nxagentGetFontServerPath(char * fontServerPath) +{ + char path[256]; + + if (NXGetFontParameters(nxagentDisplay, 256, path) == True) + { + if (*path != '\0') + { + strncpy(fontServerPath, path + 1, *path); + + *(fontServerPath + *path) = '\0'; + + #ifdef TEST + fprintf(stderr, "nxagentGetFontServerPath: Got path [%s].\n", + fontServerPath); + #endif + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentGetFontServerPath: WARNING! Font server tunneling not enabled.\n"); + #endif + + return False; + } + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentGetFontServerPath: WARNING! Failed to get path for font server tunneling.\n"); + #endif + + return False; + } + + return True; +} + +void nxagentVerifyDefaultFontPath(void) +{ + struct stat dirStat; + static char *fontPath; + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Going to search for one or more valid font paths.\n"); + #endif + + fontPath = malloc(strlen(defaultFontPath) + 1); + + if (fontPath == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Unable to allocate memory for a new font path. " + "Using the default font path [%s].\n", validateString(defaultFontPath)); + #endif + + return; + } + + /* + * Set the default font path as the first choice. + */ + + strcpy(fontPath, defaultFontPath); + + if (stat(NXAGENT_DEFAULT_FONT_DIR, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the old "/usr/X11R6/lib/X11/fonts" style. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_DEFAULT_FONT_DIR)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_DEFAULT_FONT_PATH) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_DEFAULT_FONT_PATH) + 1); + } + + strcat(fontPath, NXAGENT_DEFAULT_FONT_PATH); + } + + if (stat(NXAGENT_ALTERNATE_FONT_DIR, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the new "/usr/share/X11/fonts" path. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_ALTERNATE_FONT_DIR)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH) + 1); + } + + strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH); + } + + if (stat(NXAGENT_ALTERNATE_FONT_DIR_2, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the "/usr/share/fonts/X11" path. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_ALTERNATE_FONT_DIR_2)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_2) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_2) + 1); + } + + strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH_2); + } + + if (stat(NXAGENT_ALTERNATE_FONT_DIR_3, &dirStat) == 0 && + S_ISDIR(dirStat.st_mode) != 0) + { + /* + * Let's use the "/usr/share/fonts" path. + */ + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n", + validateString(NXAGENT_ALTERNATE_FONT_DIR_3)); + #endif + + if (*fontPath != '\0') + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_3) + 2); + strcat(fontPath, ","); + } + else + { + fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_3) + 1); + } + + strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH_3); + } + + if (*fontPath == '\0') + { + #ifdef WARNING + fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Can't find a valid font directory.\n"); + + fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Using font path [%s].\n", + validateString(defaultFontPath)); + #endif + } + else + { + defaultFontPath = fontPath; + + #ifdef TEST + fprintf(stderr, "nxagentVerifyDefaultFontPath: Using font path [%s].\n", + validateString(defaultFontPath)); + #endif + } + + return; +} + +XFontStruct* nxagentLoadQueryFont(register Display *dpy, char *name, FontPtr pFont) +{ + XFontStruct* fs; + xCharInfo *xcip; + + fs = (XFontStruct *) malloc (sizeof (XFontStruct)); + + if (fs == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentLoadQueryFont: WARNING! Failed allocation of XFontStruct.\n"); + #endif + + return (XFontStruct *)NULL; + } + + #ifdef NXAGENT_RECONNECT_FONT_DEBUG + fprintf(stderr, "nxagentLoadQueryFont: Looking for font '%s'.\n", name); + #endif + + if (nxagentFontLookUp(name) == 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentLoadQueryFont: WARNING! Font not found '%s'.\n", name); + #endif + + Xfree(fs); + + return (XFontStruct *) NULL; + } + + fs -> ext_data = NULL; /* Hook for extension to hang data.*/ + fs -> fid = XLoadFont(dpy, name); /* Font id for this font. */ + fs -> direction = pFont->info.drawDirection; /* Hint about the direction font is painted. */ + fs -> min_char_or_byte2 = pFont->info.firstCol; /* First character. */ + fs -> max_char_or_byte2 = pFont->info.lastCol; /* Last character. */ + fs -> min_byte1 = pFont->info.firstRow; /* First row that exists. */ + fs -> max_byte1 = pFont->info.lastRow; /* Last row that exists. */ + fs -> all_chars_exist = pFont->info.allExist; /* Flag if all characters have nonzero size. */ + fs -> default_char = pFont->info.defaultCh; /* Char to print for undefined character. */ + fs -> n_properties = pFont->info.nprops; /* How many properties there are. */ + + /* + * If no properties defined for the font, then it is bad + * font, but shouldn't try to read nothing. + */ + + if (fs -> n_properties > 0) + { + register long nbytes; + + nbytes = pFont -> info.nprops * sizeof(XFontProp); + fs -> properties = (XFontProp *) Xalloc((unsigned) nbytes); + + if (fs -> properties == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentLoadQueryFont: WARNING! Failed allocation of XFontProp."); + #endif + + Xfree((char *) fs); + return (XFontStruct *) NULL; + } + + memmove(fs -> properties, pFont -> info.props, nbytes); + } + + xcip = (xCharInfo *) &pFont -> info.ink_minbounds; + + fs -> min_bounds.lbearing = cvtINT16toShort(xcip -> leftSideBearing); + fs -> min_bounds.rbearing = cvtINT16toShort(xcip -> rightSideBearing); + fs -> min_bounds.width = cvtINT16toShort(xcip -> characterWidth); + fs -> min_bounds.ascent = cvtINT16toShort(xcip -> ascent); + fs -> min_bounds.descent = cvtINT16toShort(xcip -> descent); + fs -> min_bounds.attributes = xcip -> attributes; + + xcip = (xCharInfo *) &pFont -> info.ink_maxbounds; + + fs -> max_bounds.lbearing = cvtINT16toShort(xcip -> leftSideBearing); + fs -> max_bounds.rbearing = cvtINT16toShort(xcip -> rightSideBearing); + fs -> max_bounds.width = cvtINT16toShort(xcip -> characterWidth); + fs -> max_bounds.ascent = cvtINT16toShort(xcip -> ascent); + fs -> max_bounds.descent = cvtINT16toShort(xcip -> descent); + fs -> max_bounds.attributes = xcip -> attributes; + + fs -> per_char = NULL; /* First_char to last_char information. */ + fs -> ascent = pFont->info.fontAscent; /* Logical extent above baseline for spacing. */ + fs -> descent = pFont->info.fontDescent; /* Logical decent below baseline for spacing. */ + + return fs; +} + +int nxagentFreeFont(XFontStruct *fs) +{ + + if (fs -> per_char) + { + #ifdef USE_XF86BIGFONT + _XF86BigfontFreeFontMetrics(fs); + #else + Xfree ((char *) fs->per_char); + #endif + } + + if (fs -> properties) + { + Xfree (fs->properties); + } + + XFree(fs); + + return 1; +} + + +int nxagentSplitString(char *string, char *fields[], int nfields, char *sep) +{ + int seplen; + int fieldlen; + int last; + int len; + int i; + + char *current; + char *next; + + seplen = strlen(sep); + len = strlen(string); + + current = string; + + i = 0; + last = 0; + + for (;;) + { + next = NULL; + + if (current < string + len) + { + next = strstr(current, sep); + } + + if (next == NULL) + { + next = string + len; + last = 1; + } + + fieldlen = next - current; + + if (i < nfields) + { + fields[i] = (char *) malloc(fieldlen + 1); + strncpy(fields[i], current, fieldlen); + *(fields[i] + fieldlen) = 0; + } + + current = next + seplen; + + i++; + + if (last == 1) + { + break; + } + } + + return i; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Font.h b/nx-X11/programs/Xserver/hw/nxagent/Font.h new file mode 100644 index 000000000..3ae086b44 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Font.h @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Font_H__ +#define __Font_H__ + +#include "fontstruct.h" +#include "resource.h" + +extern RESTYPE RT_NX_FONT; + +extern int nxagentFontPrivateIndex; + +typedef struct +{ + XFontStruct *font_struct; + char fontName[256]; + XID mirrorID; +} nxagentPrivFont; + +extern const int nxagentMaxFontNames; + +#define nxagentFontPriv(pFont) \ + ((nxagentPrivFont *)FontGetPrivate(pFont, nxagentFontPrivateIndex)) + +#define nxagentFontStruct(pFont) (nxagentFontPriv(pFont)->font_struct) + +#define nxagentFont(pFont) (nxagentFontStruct(pFont)->fid) + +Bool nxagentRealizeFont(ScreenPtr pScreen, FontPtr pFont); +Bool nxagentUnrealizeFont(ScreenPtr pScreen, FontPtr pFont); + +void nxagentFreeFontCache(void); + +void nxagentListRemoteFonts(const char *searchPattern, const int maxNames); +int nxagentFontLookUp(const char *name); +Bool nxagentFontFind(const char *name, int *pos); +void nxagentListRemoteAddName(const char *name, int status); + +int nxagentDestroyNewFontResourceType(pointer p, XID id); + +Bool nxagentDisconnectAllFonts(void); +Bool nxagentReconnectAllFonts(void *p0); + +void nxagentVerifyDefaultFontPath(void); + +int nxagentSplitString(char *string, char *fields[], int nfields, char *sep); + +#endif /* __Font_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/GC.c b/nx-X11/programs/Xserver/hw/nxagent/GC.c new file mode 100644 index 000000000..4ca069790 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/GC.c @@ -0,0 +1,1712 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "X.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "dixstruct.h" +#include "fontstruct.h" +#include "mistruct.h" +#include "region.h" + +#include "Agent.h" + +#include "Display.h" +#include "GCs.h" +#include "GCOps.h" +#include "Image.h" +#include "Drawable.h" +#include "Pixmaps.h" +#include "Font.h" +#include "Colormap.h" +#include "Trap.h" +#include "Screen.h" +#include "Pixels.h" + +#include "../../fb/fb.h" + +RESTYPE RT_NX_GC; +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int nxagentGCPrivateIndex; + +nxagentGraphicContextsPtr nxagentGraphicContexts; +int nxagentGraphicContextsSize; + +void nxagentDisconnectGraphicContexts(void); +GCPtr nxagentCreateGraphicContext(int depth); + +static void nxagentReconnectGC(void*, XID, void*); +static void nxagentReconnectClip(GCPtr, int, pointer, int); +static int nxagentCompareRegions(RegionPtr, RegionPtr); + +struct nxagentGCRec +{ + GCPtr pGC; + XlibGC gc; + struct nxagentGCRec *next; +}; + +static struct +{ + struct nxagentGCRec *first; + struct nxagentGCRec *last; + int size; +} nxagentGCList = { NULL, NULL, 0 }; + +static struct nxagentGCRec *nxagentGetFirstGC(void); + +static void nxagentRestoreGCList(void); + +static GCFuncs nxagentFuncs = +{ + nxagentValidateGC, + nxagentChangeGC, + nxagentCopyGC, + nxagentDestroyGC, + nxagentChangeClip, + nxagentDestroyClip, + nxagentCopyClip, +}; + +static GCOps nxagentOps = +{ + nxagentFillSpans, + nxagentSetSpans, + nxagentPutImage, + nxagentCopyArea, + nxagentCopyPlane, + nxagentPolyPoint, + nxagentPolyLines, + nxagentPolySegment, + nxagentPolyRectangle, + nxagentPolyArc, + nxagentFillPolygon, + nxagentPolyFillRect, + nxagentPolyFillArc, + nxagentPolyText8, + nxagentPolyText16, + nxagentImageText8, + nxagentImageText16, + nxagentImageGlyphBlt, + nxagentPolyGlyphBlt, + nxagentPushPixels +}; + +Bool nxagentCreateGC(GCPtr pGC) +{ + FbGCPrivPtr pPriv; + + pGC->clientClipType = CT_NONE; + pGC->clientClip = NULL; + + pGC->funcs = &nxagentFuncs; + pGC->ops = &nxagentOps; + + pGC->miTranslate = 1; + + if (pGC -> stipple && !nxagentPixmapIsVirtual(pGC -> stipple)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentCreateGC: GC at [%p] got real stipple at [%p] switched to virtual.\n", + (void*)pGC, (void*)pGC -> stipple); + #endif + + pGC -> stipple = nxagentVirtualPixmap(pGC -> stipple); + } + + /* + * We create the GC based on the default + * drawables. The proxy knows this and + * optimizes the encoding of the create + * GC message to include the id of the + * drawable in the checksum. + */ + + nxagentGCPriv(pGC)->gc = XCreateGC(nxagentDisplay, + nxagentDefaultDrawables[pGC->depth], + 0L, NULL); + + #ifdef TEST + fprintf(stderr, "nxagentCreateGC: GC [%p]\n", (void *) pGC); + #endif + + pPriv = (pGC)->devPrivates[fbGCPrivateIndex].ptr; + + fbGetRotatedPixmap(pGC) = 0; + fbGetExpose(pGC) = 1; + fbGetFreeCompClip(pGC) = 0; + fbGetCompositeClip(pGC) = 0; + + pPriv->bpp = BitsPerPixel (pGC->depth); + + nxagentGCPriv(pGC)->nClipRects = 0; + + memset(&(nxagentGCPriv(pGC) -> lastServerValues), 0, sizeof(XGCValues)); + + /* + * Init to default GC values. + */ + + nxagentGCPriv(pGC) -> lastServerValues.background = 1; + + nxagentGCPriv(pGC) -> lastServerValues.plane_mask = ~0; + + nxagentGCPriv(pGC) -> lastServerValues.graphics_exposures = 1; + + nxagentGCPriv(pGC) -> lastServerValues.dashes = 4; + + nxagentGCPriv(pGC) -> mid = FakeClientID(serverClient -> index); + + nxagentGCPriv(pGC) -> pPixmap = NULL; + + AddResource(nxagentGCPriv(pGC) -> mid, RT_NX_GC, (pointer) pGC); + + return True; +} + +void nxagentValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + PixmapPtr lastTile, lastStipple; + + DrawablePtr pVirtual = (pDrawable -> type == DRAWABLE_PIXMAP) ? + nxagentVirtualDrawable(pDrawable) : + pDrawable; + + #ifdef TEST + fprintf(stderr, "nxagentValidateGC: Going to validate GC at [%p] for drawable at [%p] with changes [%lx].\n", + (void *) pGC, (void *) pDrawable, changes); + #endif + + pGC->lastWinOrg.x = pDrawable->x; + pGC->lastWinOrg.y = pDrawable->y; + + if (!pGC -> tileIsPixel && !nxagentPixmapIsVirtual(pGC -> tile.pixmap)) + { + pGC -> tile.pixmap = nxagentVirtualPixmap(pGC -> tile.pixmap); + } + + lastTile = pGC -> tile.pixmap; + + lastStipple = pGC->stipple; + + if (lastStipple) + { + pGC->stipple = nxagentVirtualPixmap(pGC->stipple); + } + + #ifdef TEST + fprintf(stderr, "nxagentValidateGC: Drawable at [%p] has type [%s] virtual [%p] bits per pixel [%d].\n", + (void *) pDrawable, (pDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pVirtual, pVirtual -> bitsPerPixel); + #endif + + if (pVirtual -> bitsPerPixel == 0) + { + /* + * Don't enter fbValidateGC() with 0 bpp + * or agent will block in a endless loop. + */ + + #ifdef WARNING + fprintf(stderr, "nxagentValidateGC: WARNING! Virtual drawable at [%p] has invalid bits per pixel.\n", + (void *) pVirtual); + + fprintf(stderr, "nxagentValidateGC: WARNING! While validating GC at [%p] for drawable at [%p] with changes [%lx].\n", + (void *) pGC, (void *) pDrawable, changes); + + fprintf(stderr, "nxagentValidateGC: WARNING! Bad drawable at [%p] has type [%s] virtual [%p] bits per pixel [%d].\n", + (void *) pDrawable, (pDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pVirtual, pVirtual -> bitsPerPixel); + #endif + } + else + { + fbValidateGC(pGC, changes, pVirtual); + } + + if (pGC->tile.pixmap != lastTile) + { + #ifdef WARNING + fprintf(stderr, "nxagentValidateGC: WARNING! Transforming pixmap at [%p] virtual at [%p] " + "in virtual pixmap.\n", (void *) nxagentPixmapPriv(pGC -> tile.pixmap) -> pRealPixmap, + (void *) nxagentPixmapPriv(pGC -> tile.pixmap) -> pRealPixmap); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentValidateGC: GC [%p] new tile [%p] from fb set as virtual\n", + (void *) pGC, (void *) pGC->tile.pixmap); + #endif + + nxagentPixmapIsVirtual(pGC->tile.pixmap) = True; + nxagentRealPixmap(pGC->tile.pixmap) = nxagentRealPixmap(lastTile); + + if (nxagentRealPixmap(lastTile)) + { + nxagentPixmapPriv(nxagentRealPixmap(lastTile))->pVirtualPixmap = pGC->tile.pixmap; + } + } + + pGC->stipple = lastStipple; +} + +void nxagentChangeGC(GCPtr pGC, unsigned long mask) +{ + #ifdef TEST + static int nDiscarded; + #endif + + XGCValues values; + + int changeFlag = 0; + + if (mask & GCFunction) + { + values.function = pGC->alu; + + changeFlag |= nxagentTestGC(values.function, function); + } + + if (mask & GCPlaneMask) + { + values.plane_mask = pGC->planemask; + + changeFlag += nxagentTestGC(values.plane_mask, plane_mask); + } + + if (mask & GCForeground) + { + values.foreground = nxagentPixel(pGC->fgPixel); + + changeFlag += nxagentTestGC(values.foreground, foreground); + } + + if (mask & GCBackground) + { + values.background = nxagentPixel(pGC->bgPixel); + + changeFlag += nxagentTestGC(values.background, background); + } + + if (mask & GCLineWidth) + { + values.line_width = pGC->lineWidth; + + changeFlag += nxagentTestGC(values.line_width, line_width); + } + + if (mask & GCLineStyle) + { + values.line_style = pGC->lineStyle; + + changeFlag += nxagentTestGC(values.line_style, line_style); + } + + if (mask & GCCapStyle) + { + values.cap_style = pGC->capStyle; + + changeFlag += nxagentTestGC(values.cap_style, cap_style); + } + + if (mask & GCJoinStyle) + { + values.join_style = pGC->joinStyle; + + changeFlag += nxagentTestGC(values.join_style, join_style); + } + + if (mask & GCFillStyle) + { + values.fill_style = pGC->fillStyle; + + changeFlag += nxagentTestGC(values.fill_style, fill_style); + } + + if (mask & GCFillRule) + { + values.fill_rule = pGC->fillRule; + + changeFlag += nxagentTestGC(values.fill_rule, fill_rule); + } + + if (mask & GCTile) + { + if (pGC->tileIsPixel) + { + mask &= ~GCTile; + } + else + { + if (nxagentDrawableStatus((DrawablePtr) pGC -> tile.pixmap) == NotSynchronized && + nxagentGCTrap == 0) + { + /* + * If the tile is corrupted and is not too + * much large, it can be synchronized imme- + * diately. In the other cases, the tile is + * cleared with a solid color to become usa- + * ble. This approach should solve the high + * delay on slow links waiting for a back- + * ground tile to be synchronized. + */ + + if (nxagentOption(DeferLevel) >= 2 && + (pGC -> tile.pixmap -> drawable.width > 240 || + pGC -> tile.pixmap -> drawable.height > 240)) + { + #ifdef TEST + fprintf(stderr, "nxagentChangeGC: WARNING! Going to fill with solid color the corrupted tile at [%p] " + "for GC at [%p] with size [%dx%d].\n", (void *) pGC -> tile.pixmap, (void *)pGC, + ((DrawablePtr) pGC -> tile.pixmap) -> width, ((DrawablePtr) pGC -> tile.pixmap) -> height); + #endif + + nxagentFillRemoteRegion((DrawablePtr) pGC -> tile.pixmap, nxagentCorruptedRegion((DrawablePtr) pGC -> tile.pixmap)); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentChangeGC: WARNING! Synchronizing GC at [%p] due the tile at [%p] with size [%dx%d].\n", + (void *)pGC, (void *)pGC -> tile.pixmap, ((DrawablePtr) pGC -> tile.pixmap) -> width, + ((DrawablePtr) pGC -> tile.pixmap) -> height); + #endif + + nxagentSynchronizeDrawable((DrawablePtr) pGC -> tile.pixmap, DO_WAIT, NEVER_BREAK, NULL); + } + } + + values.tile = nxagentPixmap(pGC->tile.pixmap); + + pGC->tile.pixmap = nxagentVirtualPixmap(pGC->tile.pixmap); + + #ifdef TEST + fprintf(stderr, "nxagentChangeGC: New tile on GC [%p] tile is [%p]\n", + (void *) pGC, (void *) pGC->tile.pixmap); + #endif + + changeFlag += nxagentTestGC(values.tile, tile); + } + } + + if (mask & GCStipple) + { + if (nxagentDrawableStatus((DrawablePtr) pGC -> stipple) == NotSynchronized && + nxagentGCTrap == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentChangeGC: WARNING! Synchronizing GC at [%p] due the stipple at [%p].\n", + (void *)pGC, (void *)pGC -> stipple); + #endif + + nxagentSynchronizeDrawable((DrawablePtr) pGC -> stipple, DO_WAIT, NEVER_BREAK, NULL); + } + + values.stipple = nxagentPixmap(pGC->stipple); + + pGC->stipple = nxagentVirtualPixmap(pGC->stipple); + + #ifdef TEST + fprintf(stderr, "nxagentChangeGC: New stipple on GC [%p] stipple is [%p]\n", + (void *) pGC, (void *) pGC->stipple); + #endif + + changeFlag += nxagentTestGC(values.stipple, stipple); + } + + if (mask & GCTileStipXOrigin) + { + values.ts_x_origin = pGC->patOrg.x; + + changeFlag += nxagentTestGC(values.ts_x_origin, ts_x_origin); + } + + if (mask & GCTileStipYOrigin) + { + values.ts_y_origin = pGC->patOrg.y; + + changeFlag += nxagentTestGC(values.ts_y_origin, ts_y_origin); + } + + if (mask & GCFont) + { + if (!nxagentFontStruct(pGC -> font)) + { + mask &= ~GCFont; + } + else + { + values.font = nxagentFont(pGC->font); + + changeFlag += nxagentTestGC(values.font, font); + } + } + + if (mask & GCSubwindowMode) + { + values.subwindow_mode = pGC->subWindowMode; + + changeFlag += nxagentTestGC(values.subwindow_mode, subwindow_mode); + } + + if (mask & GCGraphicsExposures) + { + values.graphics_exposures = pGC->graphicsExposures; + + changeFlag += nxagentTestGC(values.graphics_exposures, graphics_exposures); + } + + if (mask & GCClipXOrigin) + { + values.clip_x_origin = pGC->clipOrg.x; + + changeFlag += nxagentTestGC(values.clip_x_origin, clip_x_origin); + } + + if (mask & GCClipYOrigin) + { + values.clip_y_origin = pGC->clipOrg.y; + + changeFlag += nxagentTestGC(values.clip_y_origin, clip_y_origin); + } + + if (mask & GCClipMask) + { + /* + * This is handled in the change clip. + */ + + mask &= ~GCClipMask; + } + + if (mask & GCDashOffset) + { + values.dash_offset = pGC->dashOffset; + + changeFlag += nxagentTestGC(values.dash_offset, dash_offset); + } + + if (mask & GCDashList) + { + mask &= ~GCDashList; + + if (nxagentGCTrap == 0) + { + XSetDashes(nxagentDisplay, nxagentGC(pGC), + pGC->dashOffset, (char *)pGC->dash, pGC->numInDashList); + } + } + + if (mask & GCArcMode) + { + values.arc_mode = pGC->arcMode; + + changeFlag += nxagentTestGC(values.arc_mode, arc_mode); + } + + if (nxagentGCTrap == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentChangeGC: Skipping change of GC at [%p] on the real X server.\n", + (void *) pGC); + #endif + + return; + } + + if (mask && changeFlag) + { + XChangeGC(nxagentDisplay, nxagentGC(pGC), mask, &values); + } + #ifdef TEST + else if (mask) + { + fprintf(stderr, "nxagentChangeGC: Discarded [%d] Mask [%lu]\n", ++nDiscarded, mask); + } + #endif +} + +void nxagentCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + #ifdef TEST + fprintf(stderr, "nxagentCopyGC: Copying the GC with source at [%p] destination " + "at [%p] mask [%lu].\n", pGCSrc, pGCDst, mask); + #endif + + /* + * The MI function doesn't do anything. + * + * miCopyGC(pGCSrc, mask, pGCDst); + */ + + XCopyGC(nxagentDisplay, nxagentGC(pGCSrc), mask, nxagentGC(pGCDst)); + + /* + * Copy the private foreground field + * of the GC if GCForeground is set. + */ + + nxagentCopyGCPriv(GCForeground,foreground,pGCSrc,mask,pGCDst); +} + +void nxagentDestroyGC(GCPtr pGC) +{ + #ifdef TEST + fprintf(stderr, "nxagentDestroyGC: GC at [%p].\n", (void *) pGC); + #endif + + if (nxagentGCPriv(pGC) -> mid != 0) + { + FreeResource(nxagentGCPriv(pGC) -> mid, RT_NONE); + } + + XFreeGC(nxagentDisplay, nxagentGC(pGC)); + + miDestroyGC(pGC); +} + +void nxagentChangeClip(GCPtr pGC, int type, pointer pValue, int nRects) +{ + int i, size; + BoxPtr pBox; + XRectangle *pRects; + int clipsMatch = 0; + + #ifdef TEST + fprintf(stderr, "nxagentChangeClip: Going to change clip on GC [%p]\n", + (void *) pGC); + #endif + + switch (type) + { + case CT_NONE: + { + clipsMatch = (pGC -> clientClipType == None); + + break; + } + case CT_REGION: + { + clipsMatch = nxagentCompareRegions(pGC -> clientClip, (RegionPtr) pValue); + + break; + } + case CT_UNSORTED: + case CT_YSORTED: + case CT_YXSORTED: + case CT_YXBANDED: + { + RegionPtr pReg = RECTS_TO_REGION(pGC->pScreen, nRects, (xRectangle *)pValue, type); + + clipsMatch = nxagentCompareRegions(pGC -> clientClip, pReg); + + REGION_DESTROY(pGC->pScreen, pReg); + + break; + } + default: + { + clipsMatch = 0; + + break; + } + } + + nxagentDestroyClipHelper(pGC); + + #ifdef TEST + fprintf(stderr, "nxagentChangeClip: Type [%d] regions clipsMatch [%d].\n", + type, clipsMatch); + #endif + + switch (type) + { + case CT_NONE: + { + if (clipsMatch == 0 && nxagentGCTrap == 0) + { + XSetClipMask(nxagentDisplay, nxagentGC(pGC), None); + } + + break; + } + case CT_REGION: + { + if (clipsMatch == 0 && nxagentGCTrap == 0) + { + nRects = REGION_NUM_RECTS((RegionPtr)pValue); + size = nRects * sizeof(*pRects); + pRects = (XRectangle *) xalloc(size); + pBox = REGION_RECTS((RegionPtr)pValue); + + for (i = nRects; i-- > 0;) + { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y, + pRects, nRects, Unsorted); + xfree((char *) pRects); + } + + break; + } + case CT_PIXMAP: + { + if (nxagentGCTrap == 0) + { + XSetClipMask(nxagentDisplay, nxagentGC(pGC), + nxagentPixmap((PixmapPtr)pValue)); + } + + pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr) pValue); + + nxagentGCPriv(pGC)->pPixmap = (PixmapPtr)pValue; + + pValue = pGC->clientClip; + + type = CT_REGION; + + break; + } + case CT_UNSORTED: + { + if (clipsMatch == 0 && nxagentGCTrap == 0) + { + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, Unsorted); + } + + break; + } + case CT_YSORTED: + { + if (clipsMatch == 0 && nxagentGCTrap == 0) + { + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YSorted); + } + + break; + } + case CT_YXSORTED: + { + if (clipsMatch == 0 && nxagentGCTrap == 0) + { + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXSorted); + } + + break; + } + case CT_YXBANDED: + { + if (clipsMatch == 0 && nxagentGCTrap == 0) + { + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXBanded); + } + + break; + } + } + + switch(type) + { + case CT_UNSORTED: + case CT_YSORTED: + case CT_YXSORTED: + case CT_YXBANDED: + { + /* + * Other parts of the server can only + * deal with CT_NONE, CT_PIXMAP and + * CT_REGION client clips. + */ + + pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nRects, + (xRectangle *)pValue, type); + xfree(pValue); + + pValue = pGC->clientClip; + + type = CT_REGION; + + break; + } + default: + { + break; + } + } + + pGC->clientClipType = type; + pGC->clientClip = pValue; + + nxagentGCPriv(pGC)->nClipRects = nRects; +} + +void nxagentDestroyClip(GCPtr pGC) +{ + miDestroyClip(pGC); + + if (pGC->clientClipType == CT_PIXMAP) + { + (*pGC->pScreen->DestroyPixmap)((PixmapPtr) (pGC->clientClip)); + } + + nxagentDestroyClipHelper(pGC); + + if (nxagentGCTrap == 0) + { + XSetClipMask(nxagentDisplay, nxagentGC(pGC), None); + } + + pGC->clientClipType = CT_NONE; + pGC->clientClip = NULL; + + nxagentGCPriv(pGC)->nClipRects = 0; +} + +void nxagentDestroyClipHelper(GCPtr pGC) +{ + switch (pGC->clientClipType) + { + default: + case CT_NONE: + break; + case CT_REGION: + REGION_DESTROY(pGC->pScreen, pGC->clientClip); + break; + case CT_PIXMAP: + nxagentDestroyPixmap((PixmapPtr)pGC->clientClip); + break; + } + + if (nxagentGCPriv(pGC)->pPixmap != NULL) + { + nxagentDestroyPixmap(nxagentGCPriv(pGC)->pPixmap); + nxagentGCPriv(pGC)->pPixmap = NULL; + } +} + +void nxagentCopyClip(GCPtr pGCDst, GCPtr pGCSrc) +{ + RegionPtr pRgn; + + #ifdef TEST + fprintf(stderr, "nxagentCopyClip: Going to copy clip from GC [%p] to GC [%p]\n", + (void *) pGCDst, (void *) pGCSrc); + #endif + + switch (pGCSrc->clientClipType) + { + case CT_REGION: + if (nxagentGCPriv(pGCSrc)->pPixmap == NULL) + { + pRgn = REGION_CREATE(pGCDst->pScreen, NULL, 1); + REGION_COPY(pGCDst->pScreen, pRgn, pGCSrc->clientClip); + nxagentChangeClip(pGCDst, CT_REGION, pRgn, 0); + } + else + { + nxagentGCPriv(pGCSrc)->pPixmap->refcnt++; + + nxagentChangeClip(pGCDst, CT_PIXMAP, nxagentGCPriv(pGCSrc)->pPixmap, 0); + } + break; + case CT_PIXMAP: + + #ifdef WARNING + fprintf(stderr, "nxagentCopyClip: WARNING! Not incrementing counter for virtual pixmap at [%p].\n", + (void *) nxagentVirtualPixmap((PixmapPtr) pGCSrc->clientClip)); + #endif + + ((PixmapPtr) pGCSrc->clientClip)->refcnt++; + + nxagentChangeClip(pGCDst, CT_PIXMAP, pGCSrc->clientClip, 0); + + break; + + case CT_NONE: + nxagentDestroyClip(pGCDst); + break; + + } +} + +static struct nxagentGCRec *nxagentGetFirstGC() +{ + struct nxagentGCRec *tmp = nxagentGCList.first; + + if (nxagentGCList.size) + { + nxagentGCList.first = nxagentGCList.first -> next; + nxagentGCList.size--; + + if (nxagentGCList.size == 0) + { + nxagentGCList.last = NULL; + } + } + + return tmp; +} + +static void nxagentFreeGCRec(struct nxagentGCRec *t) +{ + #ifdef TEST + fprintf(stderr, "nxagentFreeGCRec: Freeing record at %p GC freed at %p.\n", + (void *) t, (void *) t -> gc); + #endif + + xfree(t -> gc); + + free(t); +} + +static void nxagentRestoreGCRec(struct nxagentGCRec *t) +{ + #ifdef TEST + fprintf(stderr, "nxagentRestoreGCRec: Freeing record at %p GC freed at %p.\n", + (void*)t, (void*)t -> gc); + #endif + + if (nxagentGC(t -> pGC)) + { + xfree(nxagentGC(t -> pGC)); + } + + nxagentGC(t -> pGC) = t -> gc; + + free(t); +} + +static void nxagentAddGCToList(GCPtr pGC) +{ + struct nxagentGCRec *tempGC = malloc(sizeof(struct nxagentGCRec)); + + if (tempGC == NULL) + { + FatalError("nxagentAddGCToList: malloc failed."); + } + + #ifdef TEST + fprintf(stderr, "nxagentAddGCToList: Adding GC %p to list at memory %p list size is %d.\n", + (void *) pGC, (void *) tempGC, nxagentGCList.size); + #endif + + tempGC -> pGC = pGC; + tempGC -> gc = nxagentGC(pGC); + tempGC -> next = NULL; + + if (nxagentGCList.size == 0 || nxagentGCList.first == NULL || nxagentGCList.last == NULL) + { + nxagentGCList.first = tempGC; + } + else + { + nxagentGCList.last -> next = tempGC; + } + + nxagentGCList.last = tempGC; + nxagentGCList.size++; +} + +void nxagentFreeGCList() +{ + struct nxagentGCRec *tempGC; + + #ifdef TEST + fprintf(stderr, "nxagentFreeGCList: List size is %d first elt at %p last elt at %p.\n", + nxagentGCList.size, (void*)nxagentGCList.first, (void*)nxagentGCList.last); + #endif + + while ((tempGC = nxagentGetFirstGC())) + { + nxagentFreeGCRec(tempGC); + } +} + +static void nxagentRestoreGCList() +{ + struct nxagentGCRec *tempGC; + + #ifdef TEST + fprintf(stderr, "nxagentRestoreGCList: List size is %d first elt at %p last elt at %p.\n", + nxagentGCList.size, (void*)nxagentGCList.first, (void*)nxagentGCList.last); + #endif + + while ((tempGC = nxagentGetFirstGC())) + { + nxagentRestoreGCRec(tempGC); + } +} + +int nxagentDestroyNewGCResourceType(pointer p, XID id) +{ + /* + * Address of the destructor is set in Init.c. + */ + + #ifdef TEST + fprintf(stderr, "nxagentDestroyNewGCResourceType: Destroying mirror id [%ld] for GC at [%p].\n", + nxagentGCPriv((GCPtr) p) -> mid, (void *) p); + #endif + + nxagentGCPriv((GCPtr) p) -> mid = None; + + return 1; +} + +static void nxagentReconnectGC(void *param0, XID param1, pointer param2) +{ + XGCValues values; + unsigned long valuemask; + GCPtr pGC = (GCPtr) param0; + Bool *pBool = (Bool*)param2; + + if (pGC == NULL || !*pBool) + { + return; + } + + if (nxagentGC(pGC)) + { + nxagentAddGCToList(pGC); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectGC: GCRec %p doesn't have a valid pointer to GC data.\n", (void*)pGC); + #endif + } + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectGC: GC at [%p].\n", (void *) pGC); + #endif + + valuemask = 0; + memset(&values,0,sizeof(XGCValues)); + values.function = pGC->alu; + valuemask |= GCFunction; + values.plane_mask = pGC->planemask; + valuemask |= GCPlaneMask; + values.foreground = nxagentPixel(pGC->fgPixel); + valuemask |= GCForeground; + values.background = nxagentPixel(pGC->bgPixel); + valuemask |= GCBackground; + + values.line_width = pGC->lineWidth; + valuemask |= GCLineWidth; + values.line_style = pGC->lineStyle; + valuemask |= GCLineStyle; + values.cap_style = pGC->capStyle; + valuemask |= GCCapStyle; + values.join_style = pGC->joinStyle; + valuemask |= GCJoinStyle; + values.fill_style = pGC->fillStyle; + valuemask |= GCFillStyle; + values.fill_rule = pGC->fillRule; + valuemask |= GCFillRule; + + if (!pGC -> tileIsPixel && (pGC -> tile.pixmap != NULL)) + { + if (nxagentPixmapIsVirtual(pGC -> tile.pixmap)) + { + values.tile = nxagentPixmap(nxagentRealPixmap(pGC -> tile.pixmap)); + } + else + { + values.tile = nxagentPixmap(pGC -> tile.pixmap); + } + + valuemask |= GCTile; + } + + if (pGC->stipple != NULL) + { + if (nxagentPixmapIsVirtual(pGC -> stipple)) + { + #ifdef TEST + fprintf(stderr, "nxagentReconnectGC: Reconnecting virtual stipple [%p] for GC [%p].\n", + (void *) pGC -> stipple, (void *) pGC); + #endif + + if (nxagentPixmap(nxagentRealPixmap(pGC -> stipple)) == 0) + { + nxagentReconnectPixmap(nxagentRealPixmap(pGC -> stipple), 0, pBool); + } + + values.stipple = nxagentPixmap(nxagentRealPixmap(pGC -> stipple)); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentReconnectGC: Reconnecting stipple [%p] for GC [%p].\n", + (void *) pGC -> stipple, (void *) pGC); + #endif + + if (nxagentPixmap(pGC -> stipple) == 0) + { + nxagentReconnectPixmap(pGC -> stipple, 0, pBool); + } + + values.stipple = nxagentPixmap(pGC->stipple); + } + valuemask |= GCStipple; + } + + values.ts_x_origin = pGC->patOrg.x; + valuemask |= GCTileStipXOrigin; + values.ts_y_origin = pGC->patOrg.y; + valuemask |= GCTileStipYOrigin; + + if (pGC->font != NULL) + { + values.font = nxagentFont(pGC->font); + valuemask |= GCFont; + } + + values.subwindow_mode = pGC->subWindowMode; + valuemask |= GCSubwindowMode; + values.graphics_exposures = pGC->graphicsExposures; + valuemask |= GCGraphicsExposures; + values.clip_x_origin = pGC->clipOrg.x; + valuemask |= GCClipXOrigin; + values.clip_y_origin = pGC->clipOrg.y; + valuemask |= GCClipYOrigin; + valuemask |= GCClipMask; + values.dash_offset = pGC->dashOffset; + valuemask |= GCDashOffset; + + if (pGC->dash != NULL) + { + values.dashes = *pGC->dash; + valuemask |= GCDashList; + } + + values.arc_mode = pGC->arcMode; + valuemask |= GCArcMode; + + if ((nxagentGC(pGC) = XCreateGC(nxagentDisplay, + nxagentDefaultDrawables[pGC->depth], + valuemask, &values)) == NULL) + { + *pBool = False; + } + + nxagentReconnectClip(pGC, + pGC -> clientClipType, + pGC -> clientClip, nxagentGCPriv(pGC) -> nClipRects); + + #ifdef DEBUG + XSync(nxagentDisplay, 0); + #endif +} + +Bool nxagentReconnectAllGCs(void *p0) +{ + int flexibility; + int cid; + Bool GCSuccess = True; + + flexibility = *(int*)p0; + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectAllGCs\n"); + #endif + + /* + * The resource type RT_NX_GC is created on the + * server client only, so we can avoid to loop + * through all the clients. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_GC, nxagentReconnectGC, &GCSuccess); + + for (cid = 0; (cid < MAXCLIENTS) && GCSuccess; cid++) + { + if (clients[cid]) + { + #ifdef TEST + fprintf(stderr, "nxagentReconnectAllGCs: Going to reconnect GC of client [%d].\n", cid); + #endif + + FindClientResourcesByType(clients[cid], RT_GC, nxagentReconnectGC, &GCSuccess); + } + } + + #ifdef TEST + fprintf(stderr, "nxagentReconnectAllGCs: GCs reconnection completed.\n"); + #endif + + return GCSuccess; +} + +void nxagentDisconnectGC(pointer p0, XID x1, pointer p2) +{ + GCPtr pGC = (GCPtr) p0; + Bool* pBool = (Bool*) p2; + + if (!*pBool || !pGC) + { + if (!pGC) + { + #ifdef WARNING + fprintf(stderr, "nxagentDisconnectGC: WARNING! pGC is NULL.\n"); + #endif + } + + return; + } + + if (pGC -> stipple) + { + PixmapPtr pMap = pGC -> stipple; + + nxagentDisconnectPixmap(nxagentRealPixmap(pMap), 0, pBool); + } +} + +Bool nxagentDisconnectAllGCs() +{ + int cid; + Bool success = True; + + #ifdef DEBUG + fprintf(stderr, "nxagentDisconnectAllGCs\n"); + #endif + + /* + * The resource type RT_NX_GC is created on the + * server client only, so we can avoid to loop + * through all the clients. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_GC, + (FindResType) nxagentDisconnectGC, &success); + + for (cid = 0; (cid < MAXCLIENTS) && success; cid++) + { + if (clients[cid]) + { + #ifdef TEST + fprintf(stderr, "nxagentDisconnectAllGCs: Going to disconnect GC of client [%d].\n", cid); + #endif + + FindClientResourcesByType(clients[cid], RT_GC, + (FindResType) nxagentDisconnectGC, &success); + } + } + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectAllGCs: GCs disconnection completed.\n"); + #endif + + nxagentRestoreGCList(); + + nxagentDisconnectGraphicContexts(); + + return success; +} + +static void nxagentReconnectClip(GCPtr pGC, int type, pointer pValue, int nRects) +{ + int i, size; + BoxPtr pBox; + XRectangle *pRects; + + #ifdef TEST + fprintf(stderr, "nxagentReconnectClip: going to change clip on GC [%p]\n", + (void *) pGC); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectClip: Type is [%s].\n", (type == CT_NONE) ? + "CT_NONE" : (type == CT_REGION) ? "CT_REGION" : (type == CT_PIXMAP) ? + "CT_REGION" : "UNKNOWN"); + #endif + + switch(type) + { + case CT_NONE: + XSetClipMask(nxagentDisplay, nxagentGC(pGC), None); + break; + + case CT_REGION: + if (nxagentGCPriv(pGC)->pPixmap == NULL) + { + nRects = REGION_NUM_RECTS((RegionPtr)pValue); + size = nRects * sizeof(*pRects); + pRects = (XRectangle *) xalloc(size); + pBox = REGION_RECTS((RegionPtr)pValue); + for (i = nRects; i-- > 0;) { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + + /* + * Originally, the clip origin area were 0,0 + * but it didn't work with kedit and family, + * because it got the clip mask of the pixmap + * all traslated. + */ + + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y, + pRects, nRects, Unsorted); + xfree((char *) pRects); + } + else + { + XSetClipMask(nxagentDisplay, nxagentGC(pGC), + nxagentPixmap(nxagentGCPriv(pGC)->pPixmap)); + + XSetClipOrigin(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y); + } + + break; + + case CT_PIXMAP: + + XSetClipMask(nxagentDisplay, nxagentGC(pGC), + nxagentPixmap((PixmapPtr)pValue)); + + XSetClipOrigin(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y); + + pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr) pValue); + + nxagentGCPriv(pGC)->pPixmap = (PixmapPtr)pValue; + + pValue = pGC->clientClip; + + type = CT_REGION; + + break; + + case CT_UNSORTED: + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, Unsorted); + break; + + case CT_YSORTED: + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YSorted); + break; + + case CT_YXSORTED: + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXSorted); + break; + + case CT_YXBANDED: + XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXBanded); + break; + } + + switch(type) + { + default: + break; + + case CT_UNSORTED: + case CT_YSORTED: + case CT_YXSORTED: + case CT_YXBANDED: + + /* + * other parts of server can only deal with CT_NONE, + * CT_PIXMAP and CT_REGION client clips. + */ + + pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nRects, + (xRectangle *)pValue, type); + xfree(pValue); + pValue = pGC->clientClip; + type = CT_REGION; + + break; + } + + pGC->clientClipType = type; + pGC->clientClip = pValue; + + nxagentGCPriv(pGC)->nClipRects = nRects; +} + +static int nxagentCompareRegions(RegionPtr r1, RegionPtr r2) +{ + int i; + + /* + * It returns 1 if regions are equal, 0 otherwise + */ + + if (r1 == NULL && r2 == NULL) + { + return 1; + } + + if ((r1 == NULL) || (r2 == NULL)) + { + return 0; + } + + if (REGION_NUM_RECTS(r1) != REGION_NUM_RECTS(r2)) + { + return 0; + } + else if (REGION_NUM_RECTS(r1) == 0) + { + return 1; + } + else if ((*REGION_EXTENTS(pScreen, r1)).x1 != (*REGION_EXTENTS(pScreen, r2)).x1) return 0; + else if ((*REGION_EXTENTS(pScreen, r1)).x2 != (*REGION_EXTENTS(pScreen, r2)).x2) return 0; + else if ((*REGION_EXTENTS(pScreen, r1)).y1 != (*REGION_EXTENTS(pScreen, r2)).y1) return 0; + else if ((*REGION_EXTENTS(pScreen, r1)).y2 != (*REGION_EXTENTS(pScreen, r2)).y2) return 0; + else + { + for (i = 0; i < REGION_NUM_RECTS(r1); i++) + { + if (REGION_RECTS(r1)[i].x1 != REGION_RECTS(r2)[i].x1) return 0; + else if (REGION_RECTS(r1)[i].x2 != REGION_RECTS(r2)[i].x2) return 0; + else if (REGION_RECTS(r1)[i].y1 != REGION_RECTS(r2)[i].y1) return 0; + else if (REGION_RECTS(r1)[i].y2 != REGION_RECTS(r2)[i].y2) return 0; + } + } + + return 1; +} + +/* + * This function have to be called in the place + * of GetScratchGC if the GC will be used to per- + * form operations also on the remote X Server. + * This is why we call the XChangeGC at the end of + * the function. + */ +GCPtr nxagentGetScratchGC(unsigned depth, ScreenPtr pScreen) +{ + GCPtr pGC; + XGCValues values; + unsigned long mask; + int nxagentSaveGCTrap; + + /* + * The GC trap is temporarily disabled in + * order to allow the remote clipmask reset + * requested by GetScratchGC(). + */ + + nxagentSaveGCTrap = nxagentGCTrap; + + nxagentGCTrap = 0; + + pGC = GetScratchGC(depth, pScreen); + + nxagentGCTrap = nxagentSaveGCTrap; + + if (pGC == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentGetScratchGC: Failed to retrieve the scratch GC.\n"); + #endif + + return NULL; + } + + mask = 0; + + values.function = pGC -> alu; + mask |= GCFunction; + + values.plane_mask = pGC -> planemask; + mask |= GCPlaneMask; + + values.foreground = nxagentPixel(pGC -> fgPixel); + mask |= GCForeground; + + values.background = nxagentPixel(pGC -> bgPixel); + mask |= GCBackground; + + values.line_width = pGC -> lineWidth; + mask |= GCLineWidth; + + values.line_style = pGC -> lineStyle; + mask |= GCLineStyle; + + values.cap_style = pGC -> capStyle; + mask |= GCCapStyle; + + values.join_style = pGC -> joinStyle; + mask |= GCJoinStyle; + + values.fill_style = pGC -> fillStyle; + mask |= GCFillStyle; + + values.fill_rule = pGC -> fillRule; + mask |= GCFillRule; + + values.arc_mode = pGC -> arcMode; + mask |= GCArcMode; + + values.ts_x_origin = pGC -> patOrg.x; + mask |= GCTileStipXOrigin; + + values.ts_y_origin = pGC -> patOrg.y; + mask |= GCTileStipYOrigin; + + values.subwindow_mode = pGC -> subWindowMode; + mask |= GCSubwindowMode; + + values.graphics_exposures = pGC -> graphicsExposures; + mask |= GCGraphicsExposures; + + /* + * The GCClipMask is set to none inside + * the GetScratchGC() function. + */ + + values.clip_x_origin = pGC -> clipOrg.x; + mask |= GCClipXOrigin; + + values.clip_y_origin = pGC -> clipOrg.y; + mask |= GCClipYOrigin; + + XChangeGC(nxagentDisplay, nxagentGC(pGC), mask, &values); + + memset(&(nxagentGCPriv(pGC) -> lastServerValues), 0, sizeof(XGCValues)); + + return pGC; +} + +/* + * This function is only a wrapper for + * FreeScratchGC. + */ +void nxagentFreeScratchGC(GCPtr pGC) +{ + if (pGC == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFreeScratchGC: WARNING! pGC is NULL.\n"); + #endif + + return; + } + + FreeScratchGC(pGC); +} + +/* + * The GCs belonging to this list are used + * only in the synchronization put images, + * to be sure they preserve the default va- + * lues and to avoid XChangeGC() requests. + */ + +GCPtr nxagentGetGraphicContext(DrawablePtr pDrawable) +{ + int i; + int result; + + for (i = 0; i < nxagentGraphicContextsSize; i++) + { + if (pDrawable -> depth == nxagentGraphicContexts[i].depth) + { + #ifdef DEBUG + fprintf(stderr, "nxagentGetGraphicContext: Found a valid GC at [%p] for depth [%d].\n", + (void *) nxagentGraphicContexts[i].pGC, pDrawable -> depth); + #endif + + /* + * Reconnect the GC if needed. + */ + + if (nxagentGraphicContexts[i].dirty == 1) + { + #ifdef DEBUG + fprintf(stderr, "nxagentGetGraphicContext: Going to reconnect the GC.\n"); + #endif + + result = 1; + + nxagentReconnectGC(nxagentGraphicContexts[i].pGC, (XID) 0, &result); + + if (result == 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentGetGraphicContext: WARNING! Failed to reconnect the GC.\n"); + #endif + + return NULL; + } + + nxagentGraphicContexts[i].dirty = 0; + } + + return nxagentGraphicContexts[i].pGC; + } + } + + return nxagentCreateGraphicContext(pDrawable -> depth); +} + +GCPtr nxagentCreateGraphicContext(int depth) +{ + GCPtr pGC; + + nxagentGraphicContextsPtr nxagentGCs; + + XID attributes[2]; + + /* + * We have not found a GC, so we have + * to spread the list and add a new GC. + */ + + nxagentGCs = xrealloc(nxagentGraphicContexts, (nxagentGraphicContextsSize + 1) * sizeof(nxagentGraphicContextsRec)); + + if (nxagentGCs == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentCreateGraphicContext: Cannot allocate memory for a GC.\n"); + #endif + + return NULL; + } + + nxagentGraphicContexts = nxagentGCs; + + pGC = CreateScratchGC(nxagentDefaultScreen, depth); + + if (pGC == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentCreateGraphicContext: Failed to create a GC for depth [%d].\n", + depth); + #endif + + return NULL; + } + + /* + * Color used in nxagentFillRemoteRegion(). + */ + + attributes[0] = 0xc1c1c1; + + if (depth == 15 || depth == 16) + { + Color32to16(attributes[0]); + } + + /* + * The IncludeInferiors property is useful to + * solve problems when synchronizing windows + * covered by an invisible child. + */ + + attributes[1] = IncludeInferiors; + + ChangeGC(pGC, GCForeground | GCSubwindowMode, attributes); + + nxagentGraphicContexts[nxagentGraphicContextsSize].pGC = pGC; + nxagentGraphicContexts[nxagentGraphicContextsSize].depth = depth; + nxagentGraphicContexts[nxagentGraphicContextsSize].dirty = 0; + + nxagentGraphicContextsSize++; + + #ifdef DEBUG + fprintf(stderr, "nxagentCreateGraphicContext: GC [%p] for depth [%d] added to the list of size [%d].\n", + (void *) pGC, depth, nxagentGraphicContextsSize); + #endif + + return pGC; +} + +/* + * This initialization is called in the InitOutput() + * function immediately after opening the screen, + * which is used to create the GCs. + */ + +void nxagentAllocateGraphicContexts(void) +{ + int *depths; + + int i; + + depths = nxagentDepths; + + for (i = 0; i < nxagentNumDepths; i++) + { + nxagentCreateGraphicContext(*depths); + + depths++; + } +} + +void nxagentDisconnectGraphicContexts(void) +{ + int i; + + for (i = 0; i < nxagentGraphicContextsSize; i++) + { + nxagentGraphicContexts[i].dirty = 1; + } + + return; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/GCOps.c b/nx-X11/programs/Xserver/hw/nxagent/GCOps.c new file mode 100644 index 000000000..7a6432a8e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/GCOps.c @@ -0,0 +1,1995 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "../../fb/fb.h" + +#include "Agent.h" +#include "Composite.h" +#include "Display.h" +#include "Visual.h" +#include "Drawable.h" +#include "Pixmaps.h" +#include "GCs.h" +#include "Image.h" +#include "Font.h" +#include "Events.h" +#include "Client.h" +#include "Trap.h" +#include "Holder.h" +#include "Args.h" +#include "Screen.h" + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +/* + * Temporarily set/reset the trap. + */ + +static int nxagentSaveGCTrap; + +#define SET_GC_TRAP() \ +{ \ + nxagentSaveGCTrap = nxagentGCTrap;\ +\ + nxagentGCTrap = 1; \ +} + +#define RESET_GC_TRAP() \ +{ \ + nxagentGCTrap = nxagentSaveGCTrap; \ +} + +/* + * This is currently unused. + */ + +RegionPtr nxagentBitBlitHelper(GC *pGC); + +/* + * The NX agent implementation of the + * X server's graphics functions. + */ + +void nxagentFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans, + xPoint *pPoints, int *pWidths, int fSorted) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to FillSpans on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbFillSpans(nxagentVirtualDrawable(pDrawable), pGC, nSpans, pPoints, pWidths, fSorted); + } + else + { + fbFillSpans(pDrawable, pGC, nSpans, pPoints, pWidths, fSorted); + } +} + +void nxagentSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc, + xPoint *pPoints, int *pWidths, int nSpans, int fSorted) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to SetSpans on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbSetSpans(nxagentVirtualDrawable(pDrawable), pGC, pSrc, pPoints, pWidths, nSpans, fSorted); + } + else + { + fbSetSpans(pDrawable, pGC, pSrc, pPoints, pWidths, nSpans, fSorted); + } +} + +void nxagentGetSpans(DrawablePtr pDrawable, int maxWidth, xPoint *pPoints, + int *pWidths, int nSpans, char *pBuffer) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: going to GetSpans on FB pixmap [%p].\n", + (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbGetSpans(nxagentVirtualDrawable(pDrawable), maxWidth, pPoints, pWidths, nSpans, pBuffer); + } + else + { + fbGetSpans(pDrawable, maxWidth, pPoints, pWidths, nSpans, pBuffer); + } +} + +void nxagentQueryBestSize(int class, unsigned short *pwidth, + unsigned short *pheight, ScreenPtr pScreen) +{ + unsigned width, test; + + switch(class) + { + case CursorShape: + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + case TileShape: + case StippleShape: + width = *pwidth; + if (!width) break; + /* Return the closes power of two not less than what they gave me */ + test = 0x80000000; + /* Find the highest 1 bit in the width given */ + while(!(test & width)) + test >>= 1; + /* If their number is greater than that, bump up to the next + * power of two */ + if((test - 1) & width) + test <<= 1; + *pwidth = test; + /* We don't care what height they use */ + break; + } +} + +RegionPtr nxagentBitBlitHelper(GC *pGC) +{ + #ifdef TEST + fprintf(stderr, "nxagentBitBlitHelper: Called for GC at [%p].\n", (void *) pGC); + #endif + + /* + * Force NullRegion. We consider enough the graphics + * expose events generated internally by the nxagent + * server. + */ + + #ifdef TEST + fprintf(stderr, "nxagentBitBlitHelper: WARNING! Skipping check on exposures events.\n"); + #endif + + return NullRegion; +} + +/* + * The deferring of X_RenderCompositeTrapezoids caused + * an ugly effect on pulldown menu: as the background + * may be not synchronized, the text floats in an invi- + * sible window. To avoid such effects, we use a system + * to guess if the destination target of a copy area + * is a popup, by assuming that those kind of windows + * use the override redirect property. + */ + +int nxagentWindowIsPopup(DrawablePtr pDrawable) +{ + WindowPtr parent; + + int windowIsPopup; + int level; + + if (pDrawable -> type != DRAWABLE_WINDOW) + { + return 0; + } + + windowIsPopup = 0; + + if (((WindowPtr) pDrawable) -> overrideRedirect == 1) + { + windowIsPopup = 1; + } + else + { + parent = ((WindowPtr) pDrawable) -> parent; + + /* + * Go up on the tree until a parent + * exists or 4 windows has been che- + * cked. This seems a good limit to + * up children's popup. + */ + + level = 0; + + while (parent != NULL && ++level <= 4) + { + #ifdef DEBUG + fprintf(stderr, "nxagentWindowIsPopup: Window [%p] has parent [%p] in tree with OverrideRedirect [%d] " + " Level [%d].\n", (void *) pDrawable, (void *) parent, parent -> overrideRedirect, level); + #endif + + if (parent -> overrideRedirect == 1) + { + windowIsPopup = 1; + + break; + } + + parent = parent -> parent; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentWindowIsPopup: Window [%p] %s to be a popup.\n", (void *) pDrawable, + windowIsPopup == 1 ? "seems" : "does not seem"); + #endif + + return windowIsPopup; +} + +/* + * This function returns 1 if the + * XCopyArea request must be skipped. + */ + +int nxagentDeferCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, + int height, int dstx, int dsty) +{ + RegionPtr pSrcRegion; + RegionPtr pClipRegion, pCorruptedRegion; + RegionRec corruptedRegion, tmpRegion; + + /* + * If the destination drawable is a popup + * window, we try to synchronize the source + * drawable to show a nice menu. Anyway if + * this synchronization breaks, the copy area + * is handled in the normal way. + */ + +/* +FIXME: The popup could be synchronized with one + single put image, clipped to the corrup- + ted region. As an intermediate step, the + pixmap to synchronize could be copied on + a cleared scratch pixmap, in order to + have a solid color in the clipped regions. +*/ + + if (nxagentOption(DeferLevel) >= 2 && + pSrcDrawable -> type == DRAWABLE_PIXMAP && + nxagentPixmapContainTrapezoids((PixmapPtr) pSrcDrawable) == 1 && + nxagentWindowIsPopup(pDstDrawable) == 1) + { + pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Copying to a popup menu. Source region [%d,%d,%d,%d].\n", + pSrcRegion -> extents.x1, pSrcRegion -> extents.y1, + pSrcRegion -> extents.x2, pSrcRegion -> extents.y2); + #endif + + REGION_INIT(pSrcDrawable -> pScreen, &corruptedRegion, NullBox, 1); + + REGION_INTERSECT(pSrcDrawable -> pScreen, &corruptedRegion, + pSrcRegion, nxagentCorruptedRegion(pSrcDrawable)); + + if (REGION_NIL(&corruptedRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n", + (void *) pSrcDrawable); + #endif + + nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion, EVENT_BREAK, NULL); + } + + REGION_UNINIT(pSrcDrawable -> pScreen, &corruptedRegion); + + nxagentFreeRegion(pSrcDrawable, pSrcRegion); + + if (nxagentDrawableStatus(pSrcDrawable) == Synchronized) + { + return 0; + } + } + + /* + * We are going to decide if the source drawable + * must be synchronized before using it, or if + * the copy will be clipped to the synchronized + * source region. + */ + + if ((pDstDrawable -> type == DRAWABLE_PIXMAP && + nxagentOption(DeferLevel) > 0) || nxagentOption(DeferLevel) >= 2) + { + pClipRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, + width, height); + + /* + * We called this variable pCorruptedRegion + * because in the worst case the corrupted + * region will be equal to the destination + * region. The GC's clip mask is used to + * narrow the destination. + */ + + pCorruptedRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, + width, height); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Copy area source region is [%d,%d,%d,%d].\n", + pClipRegion -> extents.x1, pClipRegion -> extents.y1, + pClipRegion -> extents.x2, pClipRegion -> extents.y2); + #endif + + REGION_SUBTRACT(pSrcDrawable -> pScreen, pClipRegion, pClipRegion, nxagentCorruptedRegion(pSrcDrawable)); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Usable copy area source region is [%d,%d,%d,%d].\n", + pClipRegion -> extents.x1, pClipRegion -> extents.y1, + pClipRegion -> extents.x2, pClipRegion -> extents.y2); + #endif + + if (pGC -> clientClip == NULL || pGC -> clientClipType != CT_REGION) + { + #ifdef WARNING + + if (pGC -> clientClipType != CT_NONE) + { + fprintf(stderr, "nxagentDeferCopyArea: WARNING! pGC [%p] has a clip type [%d].\n", + (void *) pGC, pGC -> clientClipType); + } + + #endif + + REGION_TRANSLATE(pSrcDrawable -> pScreen, pClipRegion, dstx - srcx, dsty - srcy); + } + else + { + REGION_INIT(pDstDrawable -> pScreen, &tmpRegion, NullBox, 1); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Going to modify the original GC [%p] with clip mask " + "[%d,%d,%d,%d] and origin [%d,%d].\n", + (void *) pGC, + ((RegionPtr) pGC -> clientClip) -> extents.x1, ((RegionPtr) pGC -> clientClip) -> extents.y1, + ((RegionPtr) pGC -> clientClip) -> extents.x2, ((RegionPtr) pGC -> clientClip) -> extents.y2, + pGC -> clipOrg.x, pGC -> clipOrg.y); + #endif + + REGION_COPY(pDstDrawable -> pScreen, &tmpRegion, (RegionPtr) pGC -> clientClip); + + if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0) + { + REGION_TRANSLATE(pDstDrawable -> pScreen, &tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y); + } + + REGION_TRANSLATE(pSrcDrawable -> pScreen, pClipRegion, dstx - srcx, dsty - srcy); + + REGION_INTERSECT(pSrcDrawable -> pScreen, pClipRegion, &tmpRegion, pClipRegion); + + REGION_UNINIT(pSrcDrawable -> pScreen, &tmpRegion); + } + + /* + * The corrupted region on the destination + * drawable is composed by the areas of the + * destination that we are not going to copy. + */ + + REGION_SUBTRACT(pSrcDrawable -> pScreen, pCorruptedRegion, pCorruptedRegion, pClipRegion); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Recomputed clip region is [%d,%d,%d,%d][%ld].\n", + pClipRegion -> extents.x1, pClipRegion -> extents.y1, + pClipRegion -> extents.x2, pClipRegion -> extents.y2, + REGION_NUM_RECTS(pClipRegion)); + + fprintf(stderr, "nxagentDeferCopyArea: Inherited corrupted region is [%d,%d,%d,%d][%ld].\n", + pCorruptedRegion -> extents.x1, pCorruptedRegion -> extents.y1, + pCorruptedRegion -> extents.x2, pCorruptedRegion -> extents.y2, + REGION_NUM_RECTS(pCorruptedRegion)); + #endif + + /* + * The destination drawable inherits both the + * synchronized and the corrupted region. + */ + + if (REGION_NIL(pClipRegion) == 0) + { + nxagentUnmarkCorruptedRegion(pDstDrawable, pClipRegion); + } + + if (REGION_NIL(pCorruptedRegion) == 0) + { + nxagentMarkCorruptedRegion(pDstDrawable, pCorruptedRegion); + } + + if (REGION_NIL(pClipRegion) == 0) + { + GCPtr targetGC; + + CARD32 targetAttributes[2]; + + /* + * As we want to copy only the synchronized + * areas of the source drawable, we create + * a new GC copying the original one and + * setting a new clip mask. + */ + + targetGC = GetScratchGC(pDstDrawable -> depth, pDstDrawable -> pScreen); + + ValidateGC(pDstDrawable, targetGC); + + CopyGC(pGC, targetGC, GCFunction | GCPlaneMask | GCSubwindowMode | + GCClipXOrigin | GCClipYOrigin | GCClipMask | GCForeground | + GCBackground | GCGraphicsExposures); + + if (REGION_NUM_RECTS(pClipRegion) == 1) + { + /* + * If the region to copy is formed by one + * rectangle, we change only the copy coor- + * dinates. + */ + + srcx = srcx + pClipRegion -> extents.x1 - dstx; + srcy = srcy + pClipRegion -> extents.y1 - dsty; + + dstx = pClipRegion -> extents.x1; + dsty = pClipRegion -> extents.y1; + + width = pClipRegion -> extents.x2 - pClipRegion -> extents.x1; + height = pClipRegion -> extents.y2 - pClipRegion -> extents.y1; + } + else + { + /* + * Setting the clip mask origin. This + * operation must precede the clip chan- + * ge, because the origin information is + * used in the XSetClipRectangles(). + */ + + targetAttributes[0] = 0; + targetAttributes[1] = 0; + + ChangeGC(targetGC, GCClipXOrigin | GCClipYOrigin, targetAttributes); + + /* + * Setting the new clip mask. + */ + + nxagentChangeClip(targetGC, CT_REGION, pClipRegion, 0); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Going to execute a copy area with clip mask " + "[%d,%d,%d,%d] and origin [%d,%d].\n", ((RegionPtr) targetGC -> clientClip) -> extents.x1, + ((RegionPtr) targetGC -> clientClip) -> extents.y1, + ((RegionPtr) targetGC -> clientClip) -> extents.x2, + ((RegionPtr) targetGC -> clientClip) -> extents.y2, + targetGC -> clipOrg.x, targetGC -> clipOrg.y); + #endif + } + + XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable), + nxagentGC(targetGC), srcx, srcy, width, height, dstx, dsty); + + nxagentChangeClip(targetGC, CT_NONE, NullRegion, 0); + + FreeScratchGC(targetGC); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentDeferCopyArea: The clipped region is NIL. CopyArea skipped.\n"); + #endif + + /* + * The pClipRegion is destroyed calling nxagentChangeClip(), + * so we deallocate it explicitly only if we don't change + * the clip. + */ + + nxagentFreeRegion(pSrcDrawable, pClipRegion); + } + + nxagentFreeRegion(pSrcDrawable, pCorruptedRegion); + + return 1; + } + else + { + pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Source region [%d,%d,%d,%d].\n", + pSrcRegion -> extents.x1, pSrcRegion -> extents.y1, + pSrcRegion -> extents.x2, pSrcRegion -> extents.y2); + #endif + + REGION_INIT(pSrcDrawable -> pScreen, &corruptedRegion, NullBox, 1); + + REGION_INTERSECT(pSrcDrawable -> pScreen, &corruptedRegion, + pSrcRegion, nxagentCorruptedRegion(pSrcDrawable)); + + if (REGION_NIL(&corruptedRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n", + (void *) pSrcDrawable); + #endif + + nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL); + } + + REGION_UNINIT(pSrcDrawable -> pScreen, &corruptedRegion); + + nxagentFreeRegion(pSrcDrawable, pSrcRegion); + } + + return 0; +} + +RegionPtr nxagentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, + int height, int dstx, int dsty) +{ + int leftPad = 0; + unsigned int format; + unsigned long planeMask = 0xffffffff; + + RegionPtr pDstRegion; + + int skip = 0; + + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n", + (pSrcDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable, + (pDstDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height); + #endif + + if (nxagentGCTrap == 1 || nxagentShmTrap == 1) + { + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + else + { + return fbCopyArea(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + + return NullRegion; + } + + /* + * Try to detect if the copy area is to a window + * that is unmapped or fully covered. Similarly + * to the check in Image.c, this is of little use. + */ + + if (nxagentOption(IgnoreVisibility) == 0 && pDstDrawable -> type == DRAWABLE_WINDOW && + (nxagentWindowIsVisible((WindowPtr) pDstDrawable) == 0 || + (nxagentDefaultWindowIsVisible() == 0 && nxagentCompositeEnable == 0))) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Prevented operation on fully obscured window at [%p].\n", + (void *) pDstDrawable); + #endif + + return NullRegion; + } + + /* + * If the pixmap is on shared memory, we can't + * know if the pixmap content is changed and + * so have to translate the operation in a put + * image operation. This can seriously affect + * the performance. + */ + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pSrcDrawable)) + { + char *data; + int depth, length; + + depth = pSrcDrawable -> depth; + + format = (depth == 1) ? XYPixmap : ZPixmap; + + length = nxagentImageLength(width, height, format, leftPad, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentCopyArea: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + return NullRegion; + } + + fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data); + + /* + * If the source is a shared memory pixmap, + * put the image directly to the destination. + */ + + nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty, + width, height, leftPad, format, data); + + #ifdef TEST + fprintf(stderr,"nxagentCopyArea: Realize Pixmap %p virtual %p x %d y %d w %d h %d\n", + (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable), + srcx, srcy, width, height); + #endif + + xfree(data); + + /* + * If the source is a shared memory pixmap, the + * content of the framebuffer has been placed + * directly on the destination so we can skip + * the copy area operation. + */ + + skip = 1; + } + + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] sx %d sy %d dx %d dy %d size w %d h %d\n", + ((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable, + ((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height); + #endif + + if (skip == 0 && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized) + { + skip = nxagentDeferCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, + width, height, dstx, dsty); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentCopyArea: Source drawable at [%p] already synchronized.\n", + (void *) pSrcDrawable); + } + #endif + + if (skip == 0) + { + XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable), + nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty); + + /* + * The copy area restored the synchroni- + * zation status of destination drawable. + */ + + if (nxagentDrawableStatus(pDstDrawable) == NotSynchronized) + { + pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height); + + nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion); + + nxagentFreeRegion(pDstDrawable, pDstRegion); + } + } + + if (nxagentDrawableContainGlyphs(pSrcDrawable) == 1) + { + nxagentSetDrawableContainGlyphs(pDstDrawable, 1); + } + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentIncreasePixmapUsageCounter((PixmapPtr) pSrcDrawable); + } + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + pDstDrawable -> type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to [%p]\n", + (void *) nxagentVirtualDrawable(pSrcDrawable), + (void *) nxagentVirtualDrawable(pDstDrawable)); + #endif + + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to window [%p]\n", + (void *) nxagentVirtualDrawable(pSrcDrawable), + (void *) pDstDrawable); + #endif + + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + /* + * If we are here the source drawable + * must be a window. + */ + + if (((WindowPtr) pSrcDrawable) -> viewable) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to virtual pixmap [%p]\n", + (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pDstDrawable)); + #endif + + return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + } + else + { + /* + * If we are here the source drawable + * must be a window. + */ + + if (((WindowPtr) pSrcDrawable) -> viewable) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to window [%p]\n", + (void *) pSrcDrawable, (void *) pDstDrawable); + #endif + + return fbCopyArea(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + } + + return miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, 0); +} + +RegionPtr nxagentCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long plane) +{ + unsigned int format; + int leftPad = 0; + unsigned long planeMask = 0xffffffff; + + RegionPtr pSrcRegion, pDstRegion; + RegionRec corruptedRegion; + + int skip = 0; + + #ifdef TEST + fprintf(stderr, "nxagentCopyPlane: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n", + ((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable, + ((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height); + #endif + + if (nxagentGCTrap == 1 || nxagentShmTrap == 1) + { + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else + { + return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, + dstx, dsty, plane); + } + + return NullRegion; + } + + /* + * If the pixmap is on shared memory, we can't + * know if the pixmap content is changed and + * so have to translate the operation in a put + * image operation. This can seriously affect + * the performance. + */ + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pSrcDrawable)) + { + char *data; + int depth, length; + + depth = pSrcDrawable -> depth; + + format = (depth == 1) ? XYPixmap : ZPixmap; + + length = nxagentImageLength(width, height, format, leftPad, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef DEBUG + fprintf(stderr, "nxagentCopyPlane: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + return 0; + } + + fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data); + + /* + * If the source is a shared memory pixmap, + * put the image directly to the destination. + */ + + nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty, + width, height, leftPad, format, data); + + #ifdef TEST + fprintf(stderr,"nxagentCopyPlane: Synchronize Pixmap %p virtual %p x %d y %d w %d h %d \n", + (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable), + srcx, srcy, width, height); + #endif + + xfree(data); + + /* + * If the source is a shared memory pixmap, the + * content of the framebuffer has been placed + * directly on the destination so we can skip + * the copy plane operation. + */ + + skip = 1; + } + + if (skip == 0 && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized) + { + if (pDstDrawable -> type == DRAWABLE_PIXMAP && + nxagentOption(DeferLevel) > 0) + { + pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height); + + nxagentMarkCorruptedRegion(pDstDrawable, pDstRegion); + + nxagentFreeRegion(pDstDrawable, pDstRegion); + + skip = 1; + } + else + { + pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height); + + REGION_INIT(pSrcDrawable -> pScreen, &corruptedRegion, NullBox, 1); + + REGION_INTERSECT(pSrcDrawable -> pScreen, &corruptedRegion, + pSrcRegion, nxagentCorruptedRegion(pSrcDrawable)); + + if (REGION_NIL(&corruptedRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyPlane: Forcing the synchronization of source drawable at [%p].\n", + (void *) pSrcDrawable); + #endif + + nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL); + + pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height); + + nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion); + + nxagentFreeRegion(pDstDrawable, pDstRegion); + } + + REGION_UNINIT(pSrcDrawable -> pScreen, &corruptedRegion); + + nxagentFreeRegion(pSrcDrawable, pSrcRegion); + } + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentCopyPlane: Source drawable at [%p] already synchronized.\n", + (void *) pSrcDrawable); + } + #endif + + if (skip == 0) + { + XCopyPlane(nxagentDisplay, + nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable), + nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty, plane); + } + + if ((pSrcDrawable)->type == DRAWABLE_PIXMAP && + (pDstDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyPlane: going to copy plane from FB pixmap [%p] to [%p].\n", + (void *) nxagentVirtualDrawable(pSrcDrawable), + (void *) nxagentVirtualDrawable(pDstDrawable)); + #endif + + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), pGC, + srcx, srcy, width, height, dstx, dsty, plane); + } + else + { + return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, plane); + } + + return miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, plane); +} + +void nxagentPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints) +{ + #ifdef TEST + fprintf(stderr, "nxagentPolyPoint: Drawable at [%p] GC at [%p] Points [%d].\n", + (void *) pDrawable, (void *) pGC, nPoints); + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + } + else + { + fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly point on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly point enters with virtual pixmap [%p] parent is [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawPoints(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode); + } + } + else + { + XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + } + + fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + + return; + } + else + { + XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + + fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints); + } +} + +void nxagentPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + } + else + { + fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly line on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly lines enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawLines(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode); + } + } + else + { + XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + } + + fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + + return; + } + else + { + XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + + fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints); + } +} + +void nxagentPolySegment(DrawablePtr pDrawable, GCPtr pGC, + int nSegments, xSegment *pSegments) +{ + #ifdef TEST + + if (nSegments == 1) + { + fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segment [%d,%d,%d,%d].\n", + (void *) pDrawable, (void *) pGC, + pSegments -> x1, pSegments -> y1, pSegments -> x2, pSegments -> y2); + } + else + { + fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segments [%d].\n", + (void *) pDrawable, (void *) pGC, nSegments); + } + + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments); + } + else + { + fbPolySegment(pDrawable, pGC, nSegments, pSegments); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly segment on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly segment enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawSegments(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XSegment *) pSegments, nSegments); + } + } + else + { + XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XSegment *) pSegments, nSegments); + } + + fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments); + + return; + } + else + { + XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XSegment *) pSegments, nSegments); + + fbPolySegment(pDrawable, pGC, nSegments, pSegments); + } +} + +void nxagentPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, + int nRectangles, xRectangle *pRectangles) +{ + #ifdef TEST + + if (nRectangles == 1) + { + fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangle [%d,%d][%d,%d].\n", + (void *) pDrawable, (void *) pGC, + pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height); + } + else + { + fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangles [%d].\n", + (void *) pDrawable, (void *) pGC, nRectangles); + } + + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + } + else + { + miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly rectangle on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly rectangle enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles); + } + } + else + { + XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + } + + SET_GC_TRAP(); + + miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + + RESET_GC_TRAP(); + + return; + } + else + { + XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + + SET_GC_TRAP(); + + miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles); + + RESET_GC_TRAP(); + } +} + +void nxagentPolyArc(DrawablePtr pDrawable, GCPtr pGC, + int nArcs, xArc *pArcs) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + } + else + { + fbPolyArc(pDrawable, pGC, nArcs, pArcs); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly arc on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly arc enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XArc *) pArcs, nArcs); + } + } + else + { + XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XArc *) pArcs, nArcs); + } + + fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + + return; + } + else + { + XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XArc *) pArcs, nArcs); + + fbPolyArc(pDrawable, pGC, nArcs, pArcs); + } +} + +void nxagentFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int nPoints, xPoint *pPoints) +{ + xPoint *newPoints = NULL; + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints); + } + else + { + miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints); + } + + return; + } + + /* + * The coordinate-mode must be CoordModePrevious + * to make better use of differential encoding of + * X_FillPoly request by the side of proxy. + */ + + if (mode == CoordModeOrigin) + { + int i; + + mode = CoordModePrevious; + + newPoints = xalloc(nPoints * sizeof(xPoint)); + + /* + * The first point is always relative + * to the drawable's origin. + */ + + newPoints[0].x = pPoints[0].x; + newPoints[0].y = pPoints[0].y; + + /* + * If coordinate-mode is CoordModePrevious, + * the points following the first are rela- + * tive to the previous point. + */ + + for (i = 1; i < nPoints; i++) + { + newPoints[i].x = pPoints[i].x - pPoints[i-1].x; + newPoints[i].y = pPoints[i].y - pPoints[i-1].y; + } + + pPoints = newPoints; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to fill polygon on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: fill polygon enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XFillPolygon(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XPoint *) pPoints, nPoints, shape, mode); + } + } + else + { + XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, shape, mode); + } + + SET_GC_TRAP(); + + miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints); + + RESET_GC_TRAP(); + } + else + { + XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, shape, mode); + + SET_GC_TRAP(); + + miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints); + + RESET_GC_TRAP(); + } + + if (newPoints != NULL) + { + xfree(newPoints); + } +} + +void nxagentPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, + int nRectangles, xRectangle *pRectangles) +{ + RegionPtr rectRegion; + + int inheritCorruptedRegion; + + #ifdef TEST + + if (nRectangles == 1) + { + fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangle [%d,%d][%d,%d].\n", + (void *) pDrawable, (void *) pGC, pGC -> fillStyle, + pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height); + } + else + { + fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangles [%d].\n", + (void *) pDrawable, (void *) pGC, pGC -> fillStyle, nRectangles); + } + + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + } + else + { + fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles); + } + + return; + } + + /* + * The PolyFillRect acts in two ways: if the GC + * has a corrupted tile, the operation propagates + * the corrupted region on the destination. In + * other cases, because the PolyFillRect will + * cover the destination, any corrupted region + * intersecting the target will be cleared. + */ + + inheritCorruptedRegion = 0; + + if (pGC -> fillStyle == FillTiled && + pGC -> tileIsPixel == 0 && pGC -> tile.pixmap != NULL) + { + nxagentIncreasePixmapUsageCounter(pGC -> tile.pixmap); + + if (nxagentDrawableStatus((DrawablePtr) pGC -> tile.pixmap) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentPolyFillRect: GC at [%p] uses corrupted tile pixmap at [%p]. Going to " + "corrupt the destination [%s][%p].\n", (void *) pGC, (void *) pGC -> tile.pixmap, + (pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pDrawable); + + #endif + + inheritCorruptedRegion = 1; + } + } + + if (inheritCorruptedRegion == 1 || nxagentDrawableStatus(pDrawable) == NotSynchronized) + { + rectRegion = RECTS_TO_REGION(pDrawable -> pScreen, nRectangles, pRectangles, CT_REGION); + + if (pGC -> clientClip != NULL) + { + RegionRec tmpRegion; + + REGION_INIT(pDrawable -> pScreen, &tmpRegion, NullBox, 1); + + REGION_COPY(pDrawable -> pScreen, &tmpRegion, ((RegionPtr) pGC -> clientClip)); + + if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0) + { + REGION_TRANSLATE(pDrawable -> pScreen, &tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y); + } + + REGION_INTERSECT(pDrawable -> pScreen, rectRegion, rectRegion, &tmpRegion); + + REGION_UNINIT(pDrawable -> pScreen, &tmpRegion); + } + + if (inheritCorruptedRegion == 1) + { + /* + * The fill style should affect the cor- + * rupted region propagation: if the tile + * is not completely corrupted the region + * should be 'tiled' over the destination. + */ + + nxagentMarkCorruptedRegion(pDrawable, rectRegion); + } + else + { + if (pGC -> fillStyle != FillStippled && pGC -> fillStyle != FillOpaqueStippled) + { + nxagentUnmarkCorruptedRegion(pDrawable, rectRegion); + } + else + { + /* + * The stipple mask computation could cause + * an high fragmentation of the destination + * region. An analysis should be done to exa- + * mine the better solution (e.g.rdesktop + * uses stipples to draw texts). + */ + + #ifdef TEST + fprintf(stderr, "nxagentPolyFillRect: Synchronizing the region [%d,%d,%d,%d] before using " + "the stipple at [%p].\n", rectRegion -> extents.x1, rectRegion -> extents.y1, + rectRegion -> extents.x2, rectRegion -> extents.y2, (void *) pGC -> stipple); + #endif + + nxagentSynchronizeRegion(pDrawable, rectRegion, NEVER_BREAK, NULL); + } + } + + REGION_DESTROY(pDrawable -> pScreen, rectRegion); + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly fill rect on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly fill rect enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XFillRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles); + } + } + else + { + XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + } + + fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + + return; + } + else + { + XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + + fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles); + } +} + +void nxagentPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, + int nArcs, xArc *pArcs) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + } + else + { + miPolyFillArc(pDrawable, pGC, nArcs, pArcs); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly fillarc on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly fill arc enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XFillArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XArc *) pArcs, nArcs); + } + } + else + { + XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XArc *) pArcs, nArcs); + } + + SET_GC_TRAP(); + + miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + + RESET_GC_TRAP(); + + return; + } + else + { + XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), (XArc *) pArcs, nArcs); + + SET_GC_TRAP(); + + miPolyFillArc(pDrawable, pGC, nArcs, pArcs); + + RESET_GC_TRAP(); + } +} + +int nxagentPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, char *string) +{ + int width; + + /* + * While the session is suspended + * the font structure is NULL. + */ + + if (nxagentFontStruct(pGC -> font) == NULL) + { + return x; + } + + width = XTextWidth(nxagentFontStruct(pGC->font), string, count); + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miPolyText8(pDrawable, pGC, x, y, count, string); + } + + return width + x; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly text8 on FB pixmap [%p] with string [%s].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly text8 enters with virtual pixmap [%p] parent is [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, string, count); + } + } + else + { + XDrawString(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, string, count); + } + + miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return width + x; + } + else + { + XDrawString(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + x, y, string, count); + + miPolyText8(pDrawable, pGC, x, y, count, string); + } + + return width + x; +} + +int nxagentPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, unsigned short *string) +{ + int width; + + /* + * While the session is suspended + * the font structure is NULL. + */ + + if (nxagentFontStruct(pGC -> font) == NULL) + { + return x; + } + + width = XTextWidth16(nxagentFontStruct(pGC->font), (XChar2b *)string, count); + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miPolyText16(pDrawable, pGC, x, y, count, string); + } + + return width + x; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly text16 on FB pixmap %p] with string [%s]\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly text16 enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + } + else + { + XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + + miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return width + x; + } + else + { + XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + + miPolyText16(pDrawable, pGC, x, y, count, string); + } + + return width + x; +} + +void nxagentImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, char *string) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miImageText8(pDrawable, pGC, x, y, count, string); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to image text8 on FB pixmap [%p] with string [%s].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly image text8 enters with virtual pixmap [%p] parent is [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawImageString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, string, count); + } + } + else + { + XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, string, count); + } + + miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return; + } + else + { + XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, string, count); + + miImageText8(pDrawable, pGC, x, y, count, string); + } +} + +void nxagentImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, unsigned short *string) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miImageText16(pDrawable, pGC, x, y, count, string); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to image text16 on FB pixmap [%p] with string [%s].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly image text16 enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawImageString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + } + else + { + XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + + miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return; + } + else + { + XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + + miImageText16(pDrawable, pGC, x, y, count, string); + } +} + +void nxagentImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, + pointer pGlyphBase) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to imageGlyphBlt on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbImageGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } + else + { + fbImageGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } +} + +void nxagentPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, + pointer pGlyphBase) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to PolyGlyphBlt on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbPolyGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } + else + { + fbPolyGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } +} + +void nxagentPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, + int width, int height, int x, int y) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to PushPixels on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap), + (DrawablePtr) nxagentVirtualDrawable(pDrawable), + width, height, x, y); + } + else + { + fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap), + (DrawablePtr) pDrawable, width, height, x, y); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/GCOps.h b/nx-X11/programs/Xserver/hw/nxagent/GCOps.h new file mode 100644 index 000000000..14d30e392 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/GCOps.h @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __GCOps_H__ +#define __GCOps_H__ + +/* + * Graphic operations. + */ + +void nxagentFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans, + xPoint *pPoints, int *pWidths, int fSorted); + +void nxagentSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc, + xPoint *pPoints, int *pWidths, int nSpans, int fSorted); + +void nxagentGetSpans(DrawablePtr pDrawable, int maxWidth, xPoint *pPoints, + int *pWidths, int nSpans, char *pBuffer); + +RegionPtr nxagentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, + int height, int dstx, int dsty); + +RegionPtr nxagentCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long plane); + +void nxagentQueryBestSize(int class, unsigned short *pwidth, + unsigned short *pheight, ScreenPtr pScreen); + +void nxagentPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints); + +void nxagentPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints); + +void nxagentPolySegment(DrawablePtr pDrawable, GCPtr pGC, + int nSegments, xSegment *pSegments); + +void nxagentPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, + int nRectangles, xRectangle *pRectangles); + +void nxagentPolyArc(DrawablePtr pDrawable, GCPtr pGC, + int nArcs, xArc *pArcs); + +void nxagentFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int nPoints, xPoint *pPoints); + +void nxagentPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, + int nRectangles, xRectangle *pRectangles); + +void nxagentPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, + int nArcs, xArc *pArcs); + +int nxagentPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, char *string); + +int nxagentPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, unsigned short *string); + +void nxagentImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, char *string); + +void nxagentImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, unsigned short *string); + +void nxagentImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, pointer pGlyphBase); + +void nxagentPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, pointer pGlyphBase); + +void nxagentPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, + int width, int height, int x, int y); + +#endif /* __GCOps_H__ */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/GCs.h b/nx-X11/programs/Xserver/hw/nxagent/GCs.h new file mode 100644 index 000000000..207d563ed --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/GCs.h @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __GC_H__ +#define __GC_H__ + +extern RESTYPE RT_NX_GC; + +/* This file uses the GC definition form Xlib.h as XlibGC. */ + +typedef struct { + XlibGC gc; + + int nClipRects; + + XGCValues lastServerValues; + + XID mid; + + PixmapPtr pPixmap; + +} nxagentPrivGC; + +extern int nxagentGCPrivateIndex; + +typedef struct _nxagentGraphicContextsRec +{ + int depth; + GCPtr pGC; + int dirty; + +} nxagentGraphicContextsRec; + +typedef nxagentGraphicContextsRec *nxagentGraphicContextsPtr; +extern nxagentGraphicContextsPtr nxagentGraphicContexts; +extern int nxagentGraphicContextsSize; + +#define nxagentGCPriv(pGC) \ + ((nxagentPrivGC *)((pGC) -> devPrivates[nxagentGCPrivateIndex].ptr)) + +#define nxagentGC(pGC) (nxagentGCPriv(pGC) -> gc) + +#define nxagentCopyGCPriv(valueMask, valueField, src, mask, dst) \ +\ + if (mask & valueMask) \ + { \ + nxagentGCPriv(dst) -> lastServerValues.valueField = \ + nxagentGCPriv(src) -> lastServerValues.valueField; \ + } + +#define nxagentTestGC(newValue, pvalue) \ +\ + ((nxagentGCPriv(pGC) -> lastServerValues.pvalue == newValue) ? 0 : 1); \ +\ + nxagentGCPriv(pGC) -> lastServerValues.pvalue = newValue + +Bool nxagentCreateGC(GCPtr pGC); +void nxagentValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable); +void nxagentChangeGC(GCPtr pGC, unsigned long mask); +void nxagentCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +void nxagentDestroyGC(GCPtr pGC); +void nxagentChangeClip(GCPtr pGC, int type, pointer pValue, int nRects); +void nxagentDestroyClip(GCPtr pGC); +void nxagentDestroyClipHelper(GCPtr pGC); +void nxagentCopyClip(GCPtr pGCDst, GCPtr pGCSrc); + +void nxagentDisconnectGC(pointer p0, XID x1, pointer p2); +Bool nxagentDisconnectAllGCs(void); + +Bool nxagentReconnectAllGCs(void *p0); + +int nxagentDestroyNewGCResourceType(pointer p, XID id); + +void nxagentFreeGCList(void); +void nxagentInitGCSafeVector(void); + +GCPtr nxagentGetScratchGC(unsigned depth, ScreenPtr pScreen); +void nxagentFreeScratchGC(GCPtr pGC); + +GCPtr nxagentGetGraphicContext(DrawablePtr pDrawable); +void nxagentAllocateGraphicContexts(void); + +#endif /* __GC_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Handlers.c b/nx-X11/programs/Xserver/hw/nxagent/Handlers.c new file mode 100644 index 000000000..dc9770c75 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Handlers.c @@ -0,0 +1,1272 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "dixstruct.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "osdep.h" + +#include "Agent.h" +#include "Handlers.h" +#include "Display.h" +#include "Events.h" +#include "Client.h" +#include "Reconnect.h" +#include "Dialog.h" +#include "Drawable.h" +#include "Splash.h" +#include "Screen.h" +#include "Millis.h" + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +/* + * Log begin and end of the important + * handlers. + */ + +#undef BLOCKS + +/* + * If not defined, flush immediately + * upon entering the block handler. + */ + +#define FLUSH_AFTER_MULTIPLE_READS + +/* + * Introduce a small delay after each + * loop if the session is down. The + * value is in milliseconds. + */ + +#define LOOP_DELAY_IF_DOWN 50 + +/* + * The soft limit should roughly match + * the size of the Xlib I/O buffer. + */ + +#define BYTES_BEFORE_SOFT_TOKEN 2048 +#define BYTES_BEFORE_HARD_TOKEN 65536 + +/* + * Maximum number of synchronization + * requests before waiting for the + * remote. + */ + +#define TOKENS_PENDING_LIMIT 8 + +/* + * Limits are very unobtrusive. We don't + * want to interfere with the normal + * dispatching. + */ + +#define BYTES_BEFORE_YIELD 1048576 +#define TIME_BEFORE_YIELD 500 + +/* + * Dinamically reduce the display buffer + * size after a congestion. + */ + +#undef DYNAMIC_DISPLAY_BUFFER + +/* + * Minimum display buffer size. + */ + +#define MINIMUM_DISPLAY_BUFFER 512 + +/* + * Used in the handling of the X desktop + * manager protocol. + */ + +int nxagentXdmcpUp = 0; +int nxagentXdmcpAlertUp = 0; + +/* + * Also used in the block, wakeup and + * sync handlers. + */ + +int nxagentBuffer; +int nxagentBlocking; +int nxagentCongestion; + +double nxagentBytesIn; +double nxagentBytesOut; + +/* + * Total number of descriptors ready + * as reported by the wakeup handler. + */ + +int nxagentReady; + +/* + * Timestamp of the last write to the + * remote display. + */ + +int nxagentFlush; + +/* + * Arbitrate the bandwidth among our + * clients. + */ + +struct _TokensRec nxagentTokens = { 0, 0, 0 }; +struct _DispatchRec nxagentDispatch = { UNDEFINED, 0, 0, 0 }; + +/* + * Called just before blocking, waiting + * for our clients or the X server. + */ + +void nxagentBlockHandler(pointer data, struct timeval **timeout, pointer mask) +{ + /* + * Zero timeout. + */ + + static struct timeval zero; + + /* + * Current timestamp. + */ + + static int now; + + /* + * Pending bytes to write to the + * network. + */ + + static int flushable; + + /* + * Set if we need to synchronize + * any drawable. + */ + + static int synchronize; + + #ifdef BLOCKS + fprintf(stderr, "[Begin block]\n"); + #endif + + now = GetTimeInMillis(); + + if (nxagentNeedConnectionChange() == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Calling nxagentHandleConnectionChanges " + "with ioError [%d] sigHup [%d].\n", nxagentException.ioError, nxagentException.sigHup); + #endif + + nxagentHandleConnectionChanges(); + } + + if (nxagentOption(Rootless) && + nxagentLastWindowDestroyed && nxagentRootlessDialogPid == 0 && + now > nxagentLastWindowDestroyedTime + 30 * 1000) + { + #ifdef WARNING + fprintf(stderr, "nxagentBlockHandler: No application running. Closing the session.\n"); + #endif + + nxagentTerminateSession(); + } + + #ifdef TEST + + if (nxagentLastWindowDestroyed == 1) + { + fprintf(stderr, "nxagentBlockHandler: Elapsed time [%lu].\n", + now - nxagentLastWindowDestroyedTime); + } + + #endif + + /* + * Slow down the agent if the session is + * not connected to a valid display. + */ + + if (NXDisplayError(nxagentDisplay) == 1 && nxagentShadowCounter == 0) + { + usleep(LOOP_DELAY_IF_DOWN * 1000); + + now = GetTimeInMillis(); + } + + /* + * Update the shadow display. This is + * only for test purposes. + */ + + #ifdef DUMP + + nxagentPixmapOnShadowDisplay(NULL); + + nxagentFbOnShadowDisplay(); + + #endif + + /* + * We need this here because some window + * configuration changes can be generated + * by the X server outside the control of + * the DIX. + */ + + nxagentFlushConfigureWindow(); + + /* + * Check whether there is any drawable to + * synchronize. + */ + + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Checking synchronization at %s with " + "[%d][%d][%d].\n", GetTimeInMillisAsString(), nxagentCorruptedWindows, + nxagentCorruptedBackgrounds, nxagentCorruptedPixmaps); + #endif + + synchronize = (nxagentCorruptedWindows > 0 || + nxagentCorruptedBackgrounds > 0 || + nxagentCorruptedPixmaps > 0); + + /* + * The synchronization function requires a mask as + * parameter: + * + * EVENT_BREAK Breaks if an user input, like + * a key press or a mouse move, + * is detected. + * + * CONGESTION_BREAK Breaks if the congestion beco- + * mes greater than 4. + * + * BLOCKING_BREAK Breaks if the display descript- + * or becomes blocked for write + * during the loop. + * + * ALWAYS_BREAK Any of the previous conditions + * is met. + * + * NEVER_BREAK The loop continues until all + * the drawables are synchronized. + */ + + if (synchronize == 1) + { + /* + * We should not enter the synchronization + * loop if there is any user input pending, + * i.e. if we are in the middle of a scroll + * operation. + */ + + if (nxagentForceSynchronization == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Going to force a synchronization at %s.\n", + GetTimeInMillisAsString()); + #endif + + nxagentSynchronizationLoop(NEVER_BREAK); + + nxagentForceSynchronization = 0; + } + else if (nxagentUserInput(NULL) == 0 && + nxagentBlocking == 0 && + nxagentCongestion <= 4) + { + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Going to synchronize at %s.\n", + GetTimeInMillisAsString()); + #endif + + nxagentSynchronizationLoop(ALWAYS_BREAK); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentBlockHandler: Not synchronizing with [%d][%d].\n", + nxagentBlocking, nxagentCongestion); + } + #endif + + /* + * Check if we have more corrupted resources + * and whether the conditions are satisfied + * to continue with the synchronization. + */ + + synchronize = (nxagentCongestion <= 4 && + (nxagentCorruptedWindows > 0 || + nxagentCorruptedBackgrounds > 0 || + nxagentCorruptedPixmaps > 0)); + + if (synchronize == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Setting a zero timeout with [%d][%d][%d] and " + "congestion [%d].\n", nxagentCorruptedWindows, nxagentCorruptedBackgrounds, + nxagentCorruptedPixmaps, nxagentCongestion); + #endif + + zero.tv_sec = 0; + zero.tv_usec = 0; + + *timeout = &zero; + } + #ifdef TEST + else + { + if (nxagentCorruptedWindows == 0 && + nxagentCorruptedBackgrounds == 0 && + nxagentCorruptedPixmaps == 0) + { + fprintf(stderr, "nxagentBlockHandler: Nothing more to synchronize at %s.\n", + GetTimeInMillisAsString()); + } + else + { + fprintf(stderr, "nxagentBlockHandler: Delaying synchronization with [%d][%d][%d] and " + "congestion [%d].\n", nxagentCorruptedWindows, nxagentCorruptedBackgrounds, + nxagentCorruptedPixmaps, nxagentCongestion); + } + } + #endif + } + + /* + * If the remote X server is blocking, reduce the + * amount of data sent in a single display update + * by reducing the size of the display buffer. + */ + + #ifdef DYNAMIC_DISPLAY_BUFFER + + if (nxagentBlocking == 1 && + nxagentBuffer > MINIMUM_DISPLAY_BUFFER) + { + nxagentBuffer >>= 1; + + if (nxagentBuffer < MINIMUM_DISPLAY_BUFFER) + { + nxagentBuffer = MINIMUM_DISPLAY_BUFFER; + } + + #ifdef TEST + fprintf(stderr, "nxagentDispatchHandler: Reducing the display buffer to [%d] bytes.\n", + nxagentBuffer); + #endif + + NXSetDisplayBuffer(nxagentDisplay, nxagentBuffer); + } + else if (nxagentBuffer < nxagentOption(DisplayBuffer) && + nxagentCongestion == 0) + { + nxagentBuffer = nxagentOption(DisplayBuffer); + + #ifdef TEST + fprintf(stderr, "nxagentDispatchHandler: Increasing the display buffer to [%d] bytes.\n", + nxagentBuffer); + #endif + + NXSetDisplayBuffer(nxagentDisplay, nxagentBuffer); + } + + #endif /* #ifdef DYNAMIC_DISPLAY_BUFFER */ + + /* + * Dispatch to the clients the events that + * may have become available. + */ + + if (nxagentPendingEvents(nxagentDisplay) > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Reading the events available.\n"); + #endif + + nxagentDispatchEvents(NULL); + } + + /* + * Check if there is any data remaining, + * either in the display buffer or in + * the NX transport. + */ + + flushable = NXDisplayFlushable(nxagentDisplay); + + if (flushable > 0) + { + #ifdef FLUSH_AFTER_MULTIPLE_READS + + /* + * Flush all the outstanding data if + * the wakeup handler didn't detect + * any activity. + */ + + if (nxagentReady == 0 || now - nxagentFlush >= + nxagentOption(DisplayCoalescence)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentBlockHandler: Flushing the display with [%d] bytes to flush.\n", + flushable); + #endif + + NXFlushDisplay(nxagentDisplay, NXFlushLink); + + /* + * New events may have become available + * after the flush. + */ + + if (nxagentPendingEvents(nxagentDisplay) > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Reading the events available.\n"); + #endif + + nxagentDispatchEvents(NULL); + } + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentBlockHandler: Delaying flush with [%d][%d] and [%d] bytes.\n", + synchronize, nxagentReady, flushable); + #endif + + zero.tv_sec = 0; + zero.tv_usec = 0; + + *timeout = &zero; + } + + #else /* #ifdef FLUSH_AFTER_MULTIPLE_READS */ + + /* + * We are entering the select. Tell the NX + * transport to write any produced data to + * the remote end. + */ + + NXFlushDisplay(nxagentDisplay, NXFlushLink); + + if (nxagentPendingEvents(nxagentDisplay) > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Reading the events available.\n"); + #endif + + nxagentDispatchEvents(NULL); + } + + #endif /* #ifdef FLUSH_AFTER_MULTIPLE_READS */ + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentBlockHandler: Nothing to flush with [%d][%d].\n", + synchronize, nxagentReady); + #endif + + if (nxagentQueuedEvents(nxagentDisplay) > 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentBlockHandler: WARNING! Forcing a null timeout with events queued.\n"); + #endif + + zero.tv_sec = 0; + zero.tv_usec = 0; + + *timeout = &zero; + } + } + + /* + * WaitForSomething() sets a zero timeout if there + * are clients with input, but doesn't stop the + * timer. The select is then interrupted to update + * the schedule time even if, what the dispatcher + * cares, is only the number of ticks at the time + * the client is scheduled in. + */ + + #ifdef SMART_SCHEDULE + + #ifdef DEBUG + fprintf(stderr, "nxagentBlockHandler: Stopping the smart schedule timer.\n"); + #endif + + nxagentStopTimer(); + + #endif + + #ifdef BLOCKS + fprintf(stderr, "[End block]\n"); + #endif +} + +void nxagentWakeupHandler(pointer data, int count, pointer mask) +{ + #ifdef BLOCKS + fprintf(stderr, "[Begin wakeup]\n"); + #endif + + if (nxagentException.sigHup || nxagentException.ioError) + { + #ifdef TEST + fprintf(stderr,"nxagentWakeupHandler: Got SIGHUP or I/O error.\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentBlockHandler: Calling nxagentHandleConnectionStates " + "with ioError [%d] sigHup [%d].\n", nxagentException.ioError, nxagentException.sigHup); + #endif + + nxagentHandleConnectionStates(); + } + + #ifdef SMART_SCHEDULE + + if (SmartScheduleDisable == 1) + { + + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentWakeupHandler: Resetting the dispatch state after wakeup.\n"); + #endif + + nxagentDispatch.start = GetTimeInMillis(); + + nxagentDispatch.in = nxagentBytesIn; + nxagentDispatch.out = nxagentBytesOut; + + #ifdef SMART_SCHEDULE + + } + + #endif + + /* + * Can become true during the dispatch loop. + */ + + nxagentBlocking = 0; + + /* + * Check if we got new events. + */ + + if (count > 0 && FD_ISSET(nxagentXConnectionNumber, (fd_set *) mask)) + { + #ifdef TEST + fprintf(stderr, "nxagentWakeupHandler: Reading the X events with count [%d].\n", + count); + #endif + + nxagentDispatchEvents(NULL); + + #ifdef TEST + fprintf(stderr, "nxagentWakeupHandler: Removing the X descriptor from the count.\n"); + #endif + + FD_CLR(nxagentXConnectionNumber, (fd_set *) mask); + + count--; + } + else if (nxagentQueuedEvents(nxagentDisplay) == 1) + { + /* + * We may have left some events in + * the queue. + */ + + #ifdef TEST + fprintf(stderr, "nxagentWakeupHandler: Reading the queued X events with count [%d].\n", + count); + #endif + + nxagentDispatchEvents(NULL); + } + + /* + * Save the number of descriptors ready. + */ + + if (count <= 0) + { + count = (XFD_ANYSET(&ClientsWithInput) ? 1 : 0); + } + + nxagentReady = count; + + #ifdef TEST + + if (nxagentReady == 0) + { + fprintf(stderr, "nxagentWakeupHandler: No X clients found to be processed.\n"); + } + + #endif + + /* + * If the XDM connection can't be established + * we'll need to create a dialog to notify the + * user and give him/her a chance to terminate + * the session. + */ + + if (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentWakeupHandler: XdmcpState [%d].\n", XdmcpState); + #endif + + if (XdmcpState == XDM_RUN_SESSION) + { + nxagentXdmcpUp = 1; + } + + if (nxagentXdmcpUp == 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentWakeupHandler: XdmcpTime [%lu].\n", + GetTimeInMillis() - XdmcpStartTime); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentWakeupHandler: XdmcpTimeOutRtx [%d].\n", + XdmcpTimeOutRtx); + #endif + + if (nxagentXdmcpAlertUp == 0 && + GetTimeInMillis() - XdmcpStartTime >= XDM_TIMEOUT) + { + #ifdef WARNING + fprintf(stderr, "nxagentWakeupHandler: WARNING! The XDM session seems to be " + "unable to start after [%ld] ms.\n",(long int)(GetTimeInMillis() - XdmcpStartTime)); + #endif + + NXTransAlert(FAILED_XDMCP_CONNECTION_ALERT, NX_ALERT_REMOTE); + + nxagentXdmcpAlertUp = 1; + } + } + } + + #ifdef BLOCKS + fprintf(stderr, "[End wakeup]\n"); + #endif +} + +void nxagentShadowBlockHandler(pointer data, struct timeval **timeout, pointer mask) +{ + static struct timeval zero; + + int changed; + int suspended = 0; + int result; + + #ifdef BLOCKS + fprintf(stderr, "[Begin block]\n"); + #endif + + if (nxagentNeedConnectionChange() == 1) + { + nxagentHandleConnectionChanges(); + } + + if (nxagentSessionState == SESSION_DOWN) + { + usleep(50 * 1000); + } + + #ifndef __CYGWIN32__ + + if (nxagentReadEvents(nxagentDisplay) > 0 || + nxagentReadEvents(nxagentShadowDisplay) > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowBlockHandler: Reading X events queued.\n"); + #endif + + nxagentDispatchEvents(NULL); + } + + if (nxagentShadowResize == 1) + { + nxagentShadowResize = 0; + + nxagentShadowAdaptToRatio(); + } + + #else + + if (nxagentReadEvents(nxagentDisplay) > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowBlockHandler: Reading X events queued.\n"); + #endif + + nxagentDispatchEvents(NULL); + } + + #endif + + changed = 0; + + nxagentShadowPoll(nxagentShadowPixmapPtr, nxagentShadowGCPtr, nxagentShadowDepth, nxagentShadowWidth, + nxagentShadowHeight, nxagentShadowBuffer, &changed, &suspended); + + result = nxagentShadowSendUpdates(&suspended); + + if (nxagentBlocking == 0) + { + nxagentSynchronizeDrawable((DrawablePtr) nxagentShadowPixmapPtr, DONT_WAIT, + ALWAYS_BREAK, nxagentShadowWindowPtr); + } + + /* + * We are entering the select. Tell the NX + * transport to write any produced data to + * the remote end. + */ +/* +FIXME: Must queue multiple writes and handle + the events by resembling the ordinary + block handler. +*/ + + NXFlushDisplay(nxagentDisplay, NXFlushLink); + + if (*timeout == NULL) + { + *timeout = &zero; + } + + #ifdef __CYGWIN32__ + + usleep(50 * 1000); + + (*timeout) -> tv_sec = 0; + (*timeout) -> tv_usec = 50 * 1000; + + #else + + if (changed == 0) + { + (*timeout) -> tv_sec = 0; + (*timeout) -> tv_usec = 50 * 1000; + } + else + { + (*timeout) -> tv_sec = 0; + (*timeout) -> tv_usec = 0; + } + + #endif + + #ifdef BLOCKS + fprintf(stderr, "[End block]\n"); + #endif +} + +void nxagentShadowWakeupHandler(pointer data, int count, pointer mask) +{ + #ifdef BLOCKS + fprintf(stderr, "[Begin wakeup]\n"); + #endif + + if (nxagentException.sigHup || nxagentException.ioError) + { + #ifdef TEST + fprintf(stderr,"nxagentShadowWakeupHandler: Got SIGHUP or I/O error.\n"); + #endif + + nxagentHandleConnectionStates(); + } + + #ifdef SMART_SCHEDULE + + if (SmartScheduleDisable == 1) + { + + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentShadowWakeupHandler: Resetting the dispatch state after wakeup.\n"); + #endif + + nxagentDispatch.start = GetTimeInMillis(); + + nxagentDispatch.in = nxagentBytesIn; + nxagentDispatch.out = nxagentBytesOut; + + #ifdef SMART_SCHEDULE + + } + + #endif + + /* + * Can become true during the dispatch loop. + */ + + nxagentBlocking = 0; + + /* + * Check if we got new events. + */ + + if (count > 0 && FD_ISSET(nxagentXConnectionNumber, (fd_set *) mask)) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowWakeupHandler: Reading the X events with count [%d].\n", + count); + #endif + + nxagentDispatchEvents(NULL); + + #ifdef TEST + fprintf(stderr, "nxagentShadowWakeupHandler: Removing the X descriptor from the count.\n"); + #endif + + FD_CLR(nxagentXConnectionNumber, (fd_set *) mask); + + count--; + } + else if (nxagentQueuedEvents(nxagentDisplay) == 1) + { + /* + * We may have left some events in + * the queue. + */ + + #ifdef TEST + fprintf(stderr, "nxagentShadowWakeupHandler: Reading the queued X events with count [%d].\n", + count); + #endif + + nxagentDispatchEvents(NULL); + } + + /* + * Save the number of descriptors ready. + */ + + if (count <= 0) + { + count = (XFD_ANYSET(&ClientsWithInput) ? 1 : 0); + } + + nxagentReady = count; + + #ifdef TEST + + if (nxagentReady == 0) + { + fprintf(stderr, "nxagentShadowWakeupHandler: No X clients found to be processed.\n"); + } + + #endif + + #ifdef BLOCKS + fprintf(stderr, "[End wakeup]\n"); + #endif +} + +void nxagentHandleCollectInputFocusEvent(int resource) +{ + Window window; + int revert_to; + + if (NXGetCollectedInputFocus(nxagentDisplay, resource, &window, &revert_to) == 0) + { + #ifdef PANIC + fprintf(stderr, "nxagentHandleCollectInputFocusEvent: PANIC! Failed to get the input focus " + "reply for resource [%d].\n", resource); + #endif + } + + #ifdef DEBUG + fprintf(stderr, "nxagentHandleCollectInputFocusEvent: Received a sync reply with [%d] pending.\n", + nxagentTokens.pending); + #endif + + nxagentTokens.pending--; + + nxagentCongestion = (nxagentTokens.pending >= TOKENS_PENDING_LIMIT / 2); + + #ifdef TEST + fprintf(stderr, "nxagentHandleCollectInputFocusEvent: Current congestion level is [%d].\n", + nxagentCongestion); + #endif +} + +Bool nxagentCollectInputFocusPredicate(Display *display, XEvent *X, XPointer ptr) +{ + return (X -> xclient.window == 0 && + X -> xclient.message_type == 0 && + X -> xclient.format == 32 && + X -> xclient.data.l[0] == NXCollectInputFocusNotify); +} + +void nxagentDispatchHandler(ClientPtr client, int in, int out) +{ + /* + * This function is called by the dispatcher (with 0 + * bytes out) after a new request has been processed. + * It is also called by the write handler (with 0 + * bytes in) after more data has been written to the + * display. It may be optionally called in the block + * and wakeup handlers. In this case both in and out + * must be 0. + */ + + if (out > 0) + { + /* + * Called by the display write callback. + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Called with [%d] bytes written.\n", + out); + #endif + + nxagentBytesOut += out; + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Total bytes are [%.0f] in [%.0f] out.\n", + nxagentBytesIn, nxagentBytesOut); + #endif + + /* + * Don't take care of the synchronization if + * the NX transport is running. The NX trans- + * port has its own token-based control flow. + * + * We can't produce more output here because + * we are in the middle of the flush. We will + * take care of the sync requests when called + * by the dispatcher. + */ + + if (nxagentOption(LinkType) == LINK_TYPE_NONE) + { + nxagentTokens.soft += out; + + if (out > BYTES_BEFORE_HARD_TOKEN) + { + nxagentTokens.hard += out; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Sync bytes accumulated are [%d] and [%d].\n", + nxagentTokens.soft, nxagentTokens.hard); + #endif + } + + #ifdef SMART_SCHEDULE + + if (SmartScheduleDisable == 1) + { + + #endif + + /* + * Pay attention to the next client if this + * client produced enough output. + */ + + if (nxagentBytesOut - nxagentDispatch.out > BYTES_BEFORE_YIELD) + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Yielding with [%ld][%.0f][%.0f] for client [%d].\n", + GetTimeInMillis() - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in, + nxagentBytesOut - nxagentDispatch.out, nxagentDispatch.client); + #endif + + nxagentDispatch.start = GetTimeInMillis(); + + nxagentDispatch.in = nxagentBytesIn; + nxagentDispatch.out = nxagentBytesOut; + + isItTimeToYield = 1; + } + #ifdef DEBUG + else + { + fprintf(stderr, "nxagentDispatchHandler: Dispatching with [%ld][%.0f][%.0f] for client [%d].\n", + GetTimeInMillis() - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in, + nxagentBytesOut - nxagentDispatch.out, nxagentDispatch.client); + } + #endif + + #ifdef SMART_SCHEDULE + + } + + #endif + + return; + } + else if (in > 0) + { + /* + * Called by the dispatcher. + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Called with [%d] bytes processed for client [%d].\n", + in, client -> index); + #endif + + /* + * This is presently unused. + * + * nxagentClientAddBytes(client, in); + * + * #ifdef DEBUG + * fprintf(stderr, "nxagentDispatchHandler: Bytes processed for client [%d] are [%ld].\n", + * client -> index, nxagentClientBytes(client)); + * #endif + * + */ + + nxagentBytesIn += in; + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Total bytes are [%.0f] in [%.0f] out.\n", + nxagentBytesIn, nxagentBytesOut); + #endif + + /* + * When using the dumb scheduler, before reading from + * another client, the dispatcher tries to drain all + * the input from the client being processed. This + * means that, if isItTimeToYield is never set and the + * client never produces any output, we'll stick into + * the inner dispatch loop forever. + */ + + #ifdef SMART_SCHEDULE + + if (SmartScheduleDisable == 1) + { + + #endif + + if (client -> index != nxagentDispatch.client) + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Resetting the dispatch state with [%d][%d].\n", + nxagentDispatch.client, client -> index); + #endif + + nxagentDispatch.client = client -> index; + nxagentDispatch.start = GetTimeInMillis(); + + nxagentDispatch.in = nxagentBytesIn; + nxagentDispatch.out = nxagentBytesOut; + } + else + { + static unsigned long int now; + + now = GetTimeInMillis(); + + if (now - nxagentDispatch.start > TIME_BEFORE_YIELD || + nxagentBytesIn - nxagentDispatch.in > BYTES_BEFORE_YIELD) + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Yielding with [%ld][%.0f][%.0f] for client [%d].\n", + now - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in, nxagentBytesOut - + nxagentDispatch.out, nxagentDispatch.client); + #endif + + nxagentDispatch.start = now; + + nxagentDispatch.in = nxagentBytesIn; + nxagentDispatch.out = nxagentBytesOut; + + isItTimeToYield = 1; + } + #ifdef DEBUG + else + { + fprintf(stderr, "nxagentDispatchHandler: Dispatching with [%ld][%.0f][%.0f] for client [%d].\n", + now - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in, nxagentBytesOut - + nxagentDispatch.out, nxagentDispatch.client); + } + #endif + } + + #ifdef SMART_SCHEDULE + + } + + #endif + + } + + /* + * Let's see if it's time to sync. + */ + + if (nxagentOption(LinkType) == LINK_TYPE_NONE) + { + if (nxagentTokens.hard > BYTES_BEFORE_HARD_TOKEN) + { + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Requesting a hard sync reply with [%d] bytes.\n", + nxagentTokens.hard); + #endif + + XSync(nxagentDisplay, 0); + + if (nxagentPendingEvents(nxagentDisplay) > 0) + { + nxagentDispatchEvents(NULL); + } + + nxagentTokens.soft = 0; + nxagentTokens.hard = 0; + } + else if (nxagentTokens.soft > BYTES_BEFORE_SOFT_TOKEN) + { + /* + * Alternatively, the amounts of bytes + * accounted for each sync request may + * be decreased according to the number + * of pending replies already awaited. + * + * else if (nxagentTokens.soft > (BYTES_BEFORE_SOFT_TOKEN / (nxagentTokens.pending + 1))) + */ + + int resource; + + /* + * Wait eventually for the number of + * synchronization requests to return + * below the limit. + */ + + #ifdef TEST + + if (nxagentTokens.pending == TOKENS_PENDING_LIMIT) + { + fprintf(stderr, "nxagentDispatchHandler: WARNING! Waiting for the synchronization reply.\n"); + } + + #endif + + while (nxagentTokens.pending == TOKENS_PENDING_LIMIT) + { + if (nxagentWaitEvents(nxagentDisplay, NULL) == -1) + { + nxagentTokens.pending = 0; + + nxagentTokens.soft = 0; + + return; + } + + nxagentDispatchEvents(NULL); + + nxagentBlocking = 1; + } + + /* + * Send a new synchronization request. + */ + + resource = nxagentWaitForResource(NXGetCollectInputFocusResource, + nxagentCollectInputFocusPredicate); + + if (resource == -1) + { + #ifdef PANIC + fprintf(stderr, "nxagentDispatchHandler: PANIC! Cannot allocate any valid resource.\n"); + #endif + + nxagentTokens.soft = 0; + + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentDispatchHandler: Requesting a sync reply with [%d] bytes " + "and [%d] pending.\n", nxagentTokens.soft, nxagentTokens.pending); + #endif + + NXCollectInputFocus(nxagentDisplay, resource); + + NXFlushDisplay(nxagentDisplay, NXFlushBuffer); + + if (nxagentPendingEvents(nxagentDisplay) > 0) + { + nxagentDispatchEvents(NULL); + } + + nxagentTokens.pending++; + + nxagentCongestion = (nxagentTokens.pending >= TOKENS_PENDING_LIMIT / 2); + + #ifdef TEST + fprintf(stderr, "nxagentDispatchHandler: Current congestion level is [%d].\n", + nxagentCongestion); + #endif + + nxagentTokens.soft = 0; + } + } + + /* + * Check if there are events to read. + */ + + if (nxagentPendingEvents(nxagentDisplay) > 0) + { + nxagentDispatchEvents(NULL); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Handlers.h b/nx-X11/programs/Xserver/hw/nxagent/Handlers.h new file mode 100644 index 000000000..fc72c7060 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Handlers.h @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Handlers_H__ +#define __Handlers_H__ + +/* + * Current size of the display buffer. + */ + +extern int nxagentBuffer; + +/* + * Set if we had to block waiting for + * the display to become writable. + */ + +extern int nxagentBlocking; + +/* + * Current congestion level based on + * the sync requests awaited or the + * proxy tokens. + */ + +extern int nxagentCongestion; + +/* + * Bytes read from the agent's clients + * and written to the display socket. + */ + +extern double nxagentBytesIn; +extern double nxagentBytesOut; + +/* + * Total number of descriptors ready + * as reported by the wakeup handler. + */ + +extern int nxagentReady; + +/* + * Timestamp of the last write to the + * remote display. + */ + +extern int nxagentFlush; + +/* + * Let the dispatch loop yield control to + * a different client after a fair amount + * of time or after enough data has been + * processed. + */ + +struct _DispatchRec +{ + int client; + + double in; + double out; + + unsigned long start; +}; + +extern struct _DispatchRec nxagentDispatch; + +/* + * Ensure that we synchronize with the X + * server after a given amount of output + * is produced. + */ + +struct _TokensRec +{ + int soft; + int hard; + + int pending; +}; + +extern struct _TokensRec nxagentTokens; + +/* + * The agent's block and wakeup handlers. + */ + +void nxagentBlockHandler(pointer data, struct timeval **timeout, pointer mask); +void nxagentWakeupHandler(pointer data, int count, pointer mask); + +/* + * Executed after each request processed. + */ + +void nxagentDispatchHandler(ClientPtr client, int in, int out); + +void nxagentShadowBlockHandler(pointer data, struct timeval **timeout, pointer mask); +void nxagentShadowWakeupHandler(pointer data, int count, pointer mask); + +extern GCPtr nxagentShadowGCPtr; +extern unsigned char nxagentShadowDepth; +extern int nxagentShadowWidth; +extern int nxagentShadowHeight; +extern char *nxagentShadowBuffer; + +#endif /* __Handlers_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Holder.c b/nx-X11/programs/Xserver/hw/nxagent/Holder.c new file mode 100644 index 000000000..087d66017 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Holder.c @@ -0,0 +1,226 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include +#include + +#ifdef _XSERVER64 + +#include "scrnintstr.h" +#include "Agent.h" +#define GC XlibGC +#define PIXEL_ALREADY_TYPEDEFED + +#endif /* _XSERVER64 */ + +#include "pixmapstr.h" +#include "regionstr.h" +#include "resource.h" +#include "../../include/gc.h" +#include "../../include/window.h" + +#include "xpm.h" + +#include "Agent.h" +#include "Pixmaps.h" +#include "Display.h" +#include "Holder.h" +#include "Icons.h" + +#include NXAGENT_PLACEHOLDER_NAME + +#define MAXDEPTH 32 + +#define PLACEHOLDER_WIDTH 14 +#define PLACEHOLDER_HEIGHT 16 + +#define PLACEHOLDER_BORDER_COLOR_DARK 0x000000 +#define PLACEHOLDER_BORDER_COLOR_LIGHT 0xB2B2B2 + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +static Pixmap nxagentPlaceholderPixmaps[MAXDEPTH + 1]; + +void nxagentMarkPlaceholderNotLoaded(int depth) +{ + nxagentPlaceholderPixmaps[depth] = 0; +} + +void nxagentInitPlaceholder(int depth) +{ + int status; + XpmAttributes attributes; + + attributes.valuemask = XpmDepth | XpmSize; + attributes.depth = depth; + + status = XpmCreatePixmapFromData(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + placeholderXpm, nxagentPlaceholderPixmaps + depth, NULL, &attributes); + + if (status != Success) + { + FatalError("Error: Failed to create the placeholder pixmap.\n"); + } + + #ifdef TEST + fprintf(stderr, "nxagentInitPlaceholder: Created pixmap [0x%lx] with geometry [%d,%d] for depth [%d].\n", + nxagentPlaceholderPixmaps[depth], attributes.width, attributes.height, depth); + #endif +} + +void nxagentApplyPlaceholder(Drawable drawable, int x, int y, + int w, int h, int depth) +{ + /* + * Instead of the image, a white rectangle that + * covers the pixmap area is drawn, alongside + * with a black and grey line that outlines the + * boundaries of the affected area. + */ + + GC gc; + XGCValues value; + XPoint points[3]; + + value.foreground = 0xffffffff; + value.background = 0x00000000; + value.plane_mask = 0xffffffff; + value.fill_style = FillSolid; + + /* + * FIXME: Should we use a gc cache to save + * some bandwidth? + */ + + gc = XCreateGC(nxagentDisplay, drawable, GCBackground | + GCForeground | GCFillStyle | GCPlaneMask, &value); + + XFillRectangle(nxagentDisplay, drawable, gc, x, y, w, h); + + if (depth == 1) + { + return; + } + + value.foreground = PLACEHOLDER_BORDER_COLOR_DARK; + value.line_style = LineSolid; + value.line_width = 1; + + points[0].x = x; + points[0].y = y + h - 1; + points[1].x = x; + points[1].y = y; + points[2].x = x + w - 1; + points[2].y = y; + + XChangeGC(nxagentDisplay, gc, GCForeground | GCLineWidth | GCLineStyle, &value); + XDrawLines(nxagentDisplay, drawable, gc, points, 3, CoordModeOrigin); + + value.foreground = PLACEHOLDER_BORDER_COLOR_LIGHT; + value.line_style = LineSolid; + value.line_width = 1; + + points[0].x = x; + points[0].y = y + h - 1; + points[1].x = x + w - 1; + points[1].y = y + h - 1; + points[2].x = x + w - 1; + points[2].y = y; + + XChangeGC(nxagentDisplay, gc, GCForeground | GCLineWidth | GCLineStyle, &value); + XDrawLines(nxagentDisplay, drawable, gc, points, 3, CoordModeOrigin); + + /* + * We are going to apply place holder only if on region + * we have enough space for the placeholder plus three + * pixel for spacing and one for region border. + */ + + if ((w >= PLACEHOLDER_WIDTH + 8) && (h >= PLACEHOLDER_HEIGHT + 8)) + { + #ifdef TEST + fprintf(stderr, "nxagentApplyPlaceholder: drawable %lx placeholder %lx from %d %d pixmap size is %d %d " + "depth %d\n", drawable, nxagentPlaceholderPixmaps[depth], x, y, w, h, depth); + #endif + + if (nxagentPlaceholderPixmaps[depth] == 0) + { + nxagentInitPlaceholder(depth); + } + + XCopyArea(nxagentDisplay, nxagentPlaceholderPixmaps[depth], + drawable, gc, 0, 0, PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, x + 4, y + 4); + + } + + XFreeGC(nxagentDisplay, gc); + + return; +} + +#ifdef DUMP + +static char hexdigit(char c) +{ + char map[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '?'}; + + return map[c]; +} + +/* +FIXME: Please, check the implementation of the same + function in nxcomp. +*/ +char *nxagentChecksum(char *string, int length) +{ + static char md5_output[MD5_DIGEST_LENGTH * 2 + 1]; + static char md5[MD5_DIGEST_LENGTH]; + char * ret; + int i; + + memset(md5, 0, sizeof(md5)); + memset(md5_output, 0, sizeof(md5_output)); + + ret = MD5(string, length, md5); + + for (i = 0; i < MD5_DIGEST_LENGTH; i++) + { + char c = md5[i]; + + md5_output[i * 2 + 0] = hexdigit((c >> 0) & 0xF); + md5_output[i * 2 + 1] = hexdigit((c >> 4) & 0xF); + } + + return md5_output; +} + +#else + +const char *nxagentChecksum(char *data, int size) +{ + return ""; +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Holder.h b/nx-X11/programs/Xserver/hw/nxagent/Holder.h new file mode 100644 index 000000000..6dc2b8ed2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Holder.h @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Holder_H__ +#define __Holder_H__ + +void nxagentMarkPlaceholderNotLoaded(int depth); +void nxagentInitPlaceholder(int depth); +void nxagentApplyPlaceholder(Drawable drawable, int x, int y, int w, int h, int depth); + +const char *nxagentChecksum(char *data, int size); + +#endif /* __Holder_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Icons.h b/nx-X11/programs/Xserver/hw/nxagent/Icons.h new file mode 100644 index 000000000..cb2e08521 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Icons.h @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Icons_H__ +#define __Icons_H__ + +#define Pixel XpmPixel +#include +#undef Pixel + +#define NXAGENT_ICON_NAME "nxagent.xpm" + +#define NXAGENT_PLACEHOLDER_NAME "nxmissing.xpm" + +#endif /* __Icons_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Image.c b/nx-X11/programs/Xserver/hw/nxagent/Image.c new file mode 100644 index 000000000..5108046b8 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Image.c @@ -0,0 +1,1816 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "../../fb/fb.h" + +#include "Agent.h" +#include "Composite.h" +#include "Display.h" +#include "Visual.h" +#include "Drawable.h" +#include "Pixmaps.h" +#include "GCs.h" +#include "Image.h" +#include "Events.h" +#include "Client.h" +#include "Trap.h" +#include "Split.h" +#include "Args.h" +#include "Screen.h" +#include "Pixels.h" +#include "Utils.h" + +#include "NXlib.h" +#include "NXpack.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +/* + * Don't pack the images having a width, a + * height or a data size smaller or equal + * to these thresholds. + */ + +#define IMAGE_PACK_WIDTH 2 +#define IMAGE_PACK_HEIGHT 2 +#define IMAGE_PACK_LENGTH 512 + +/* + * Compress the image with a lossless encoder + * if the percentage of discrete pixels in the + * image is below this threshold. + */ + +#define IMAGE_UNIQUE_RATIO 10 + +/* + * Introduce a small delay after each image + * operation if the session is down. Value + * is in microseconds and is multiplied by + * the image data size in kilobytes. + */ + +#define IMAGE_DELAY_IF_DOWN 250 + +/* + * Preferred pack and split parameters we + * got from the NX transport. + */ + +int nxagentPackLossless = -1; +int nxagentPackMethod = -1; +int nxagentPackQuality = -1; +int nxagentSplitThreshold = -1; + +/* + * Set if images can use the alpha channel. + */ + +int nxagentAlphaEnabled = 0; +int nxagentAlphaCompat = 0; + +/* + * Used to reformat image when connecting to + * displays having different byte order. + */ + +extern void BitOrderInvert(unsigned char *, int); +extern void TwoByteSwap(unsigned char *, register int); +extern void FourByteSwap(register unsigned char *, register int); + +/* + * Store the last visual used to unpack + * the images for the given client. + */ + +static VisualID nxagentUnpackVisualId[MAX_CONNECTIONS]; + +/* + * Store the last alpha data set for the + * client. + */ + +typedef struct _UnpackAlpha +{ + char *data; + int size; + +} UnpackAlphaRec; + +typedef UnpackAlphaRec *UnpackAlphaPtr; + +static UnpackAlphaPtr nxagentUnpackAlpha[MAX_CONNECTIONS]; + +/* + * Encode the imade alpha channel by using + * a specific encoding, separating it from + * the rest of the RGB data. + */ + +static char *nxagentImageAlpha(XImage *ximage); +static void nxagentSetUnpackAlpha(DrawablePtr pDrawable, XImage *pImage, ClientPtr pClient); + +/* + * Copy the source data to the destination. + */ + +static char *nxagentImageCopy(XImage *source, XImage *destination); + +/* + * Return true if the image can be cached. + * Don't cache the images packed with the + * bitmap method as the encoding is little + * more expensive than a copy. + */ + +#define nxagentNeedCache(image, method) \ +\ + ((method) != PACK_BITMAP_16M_COLORS) + +/* + * With the bitmap encoding, if the image + * is 32 bits-per-pixel the 4th byte is not + * transmitted, so we don't need to clean + * the image. + */ + +#define nxagentNeedClean(image, method) \ +\ + ((method) == PACK_RLE_16M_COLORS || \ + (method) == PACK_RGB_16M_COLORS || \ + ((method) == PACK_BITMAP_16M_COLORS && \ + image -> bits_per_pixel != 32)) + +/* + * Collect the image cache statistics. + */ + +typedef struct _ImageStatisticsRec +{ + double partialLookups; + double partialMatches; + double partialEncoded; + double partialAdded; + + double totalLookups; + double totalMatches; + double totalEncoded; + double totalAdded; + +} ImageStatisticsRec; + +ImageStatisticsRec nxagentImageStatistics; + +int nxagentImageReformat(char *base, int nbytes, int bpp, int order) +{ + /* + * This is used whenever we need to swap the image data. + * If we got an image from a X server having a different + * endianess, we will need to redormat the image to match + * our own image-order so that ProcGetImage can return + * the expected format to the client. + */ + + switch (bpp) + { + case 1: + { + if (BITMAP_BIT_ORDER != order) + { + #ifdef TEST + fprintf(stderr, "nxagentImageReformat: Bit order invert with size [%d] " + "bits per pixel [%d] byte order [%d].\n", nbytes, bpp, order); + #endif + + BitOrderInvert((unsigned char *) base, nbytes); + } + + #if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + + nxagentImageReformat(base, nbytes, BITMAP_SCANLINE_UNIT, order); + + #endif + + break; + } + case 4: + case 8: + { + break; + } + case 16: + { + if (IMAGE_BYTE_ORDER != order) + { + #ifdef TEST + fprintf(stderr, "nxagentImageReformat: Two bytes swap with size [%d] " + "bits per pixel [%d] byte order [%d].\n", nbytes, bpp, order); + #endif + + TwoByteSwap((unsigned char *) base, nbytes); + } + + break; + } + case 32: + { + if (IMAGE_BYTE_ORDER != order) + { + #ifdef TEST + fprintf(stderr, "nxagentImageReformat: Four bytes swap with size [%d] " + "bits per pixel [%d] byte order [%d].\n", nbytes, bpp, order); + #endif + + FourByteSwap((unsigned char *) base, nbytes); + } + + break; + } + } + + return 1; +} + +int nxagentImageLength(int width, int height, int format, int leftPad, int depth) +{ + int line = 0; + + if (format == XYBitmap) + { + line = BitmapBytePad(width + leftPad); + } + else if (format == XYPixmap) + { + line = BitmapBytePad(width + leftPad); + + line *= depth; + } + else if (format == ZPixmap) + { + line = PixmapBytePad(width, depth); + } + + return line * height; +} + +int nxagentImagePad(int width, int format, int leftPad, int depth) +{ + int line = 0; + + if (format == XYBitmap) + { + line = BitmapBytePad(width + leftPad); + } + else if (format == XYPixmap) + { + line = BitmapBytePad(width + leftPad); + } + else if (format == ZPixmap) + { + line = PixmapBytePad(width, depth); + } + + return line; +} + +/* + * Only copy the data, not the structure. + * The data pointed by the destination is + * lost. Used to clone two images that + * point to the same data. + */ + +char *nxagentImageCopy(XImage *source, XImage *destination) +{ + #ifdef DEBUG + fprintf(stderr, "nxagentImageClone: Copying [%d] bytes of data from the source.\n", + source -> bytes_per_line * source -> height); + #endif + + destination -> data = Xmalloc(source -> bytes_per_line * source -> height); + + if (destination -> data == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentImageCopy: PANIC! Cannot allocate memory for the copy.\n"); + #endif + } + else + { + memcpy(destination -> data, source -> data, + source -> bytes_per_line * source -> height); + } + + return destination -> data; +} + +char *nxagentImageAlpha(XImage *image) +{ + char *pData; + + char *pSrcData; + char *pDstData; + + int size; + int offset; + + /* + * Use one byte per pixel. + */ + + size = (image -> bytes_per_line * image -> height) >> 2; + + pData = Xmalloc(size); + + if (pData == NULL) + { + return NULL; + } + + /* + * The image is supposed to be in + * server order. + */ + + offset = (image -> byte_order == MSBFirst) ? 0 : 3; + + pSrcData = image -> data; + pDstData = pData; + + while (size-- > 0) + { + *pDstData++ = *(pSrcData + offset); + + pSrcData += 4; + } + + return pData; +} + +/* + * Write down the image cache statistics + * to the buffer. + */ + +void nxagentImageStatisticsHandler(char **buffer, int type) +{ +/* +FIXME: Agent cache statistics have to be implemented. +*/ + #ifdef TEST + fprintf(stderr, "nxagentImageStatisticsHandler: STATISTICS! Statistics requested to the agent.\n"); + #endif + + *buffer = NULL; +} + +/* + * This should be called only for drawables + * having a depth of 32. In the other cases, + * it would only generate useless traffic. + */ + +void nxagentSetUnpackAlpha(DrawablePtr pDrawable, XImage *pImage, ClientPtr pClient) +{ + int resource = pClient -> index; + + unsigned int size = (pImage -> bytes_per_line * pImage -> height) >> 2; + + char *data = nxagentImageAlpha(pImage); + + if (data == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentSetUnpackAlpha: PANIC! Can't allocate data for the alpha channel.\n"); + #endif + + return; + } + + /* + * If we are synchronizing the drawable, discard + * any unpack alpha stored for the client. The + * alpha data, in fact, may be still traveling + * and so we either wait until the end of the + * split or send a fresh copy. + */ +/* +FIXME: Here the split trap is always set and so the caching of + the alpha channel is useless. I remember we set the trap + because of the cursor but why is it always set now? +*/ + #ifdef DEBUG + fprintf(stderr, "nxagentSetUnpackAlpha: Checking alpha channel for client [%d] with trap [%d].\n", + resource, nxagentSplitTrap); + #endif + + if (nxagentSplitTrap == 1 || nxagentUnpackAlpha[resource] == NULL || + nxagentUnpackAlpha[resource] -> size != size || + memcmp(nxagentUnpackAlpha[resource] -> data, data, size) != 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentSetUnpackAlpha: Sending alpha channel with width [%d] height [%d] " + "bytes per line [%d] size [%d].\n", pImage -> width, pImage -> height, + pImage -> bytes_per_line, size); + #endif + + /* + * Check if we are connected to a newer proxy + * version and so can send the alpha data in + * compressed form. + */ + + if (nxagentAlphaCompat == 0) + { + NXSetUnpackAlpha(nxagentDisplay, resource, PACK_NONE, size, data, size); + } + else + { + NXSetUnpackAlphaCompat(nxagentDisplay, resource, size, data); + } + + if (nxagentUnpackAlpha[resource] != NULL) + { + Xfree(nxagentUnpackAlpha[resource] -> data); + } + else if ((nxagentUnpackAlpha[resource] = Xmalloc(sizeof(UnpackAlphaRec))) == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentSetUnpackAlpha: PANIC! Can't allocate data for the alpha structure.\n"); + #endif + + Xfree(data); + + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentSetUnpackAlpha: Saved alpha channel for client [%d] with size [%d].\n", + resource, size); + #endif + + nxagentUnpackAlpha[resource] -> size = size; + nxagentUnpackAlpha[resource] -> data = data; + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentSetUnpackAlpha: Matched alpha channel for client [%d] with size [%d].\n", + resource, size); + #endif + + Xfree(data); + } +} + +/* + * The NX agent's implementation of the + * X server's image functions. + */ + +void nxagentPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int dstX, int dstY, int dstWidth, int dstHeight, + int leftPad, int format, char *data) +{ + int length; + + RegionPtr pRegion = NullRegion; + + int resource = 0; + int split = 0; + int cache = 1; + + #ifdef TEST + fprintf(stderr, "nxagentPutImage: Image data at [%p] drawable [%s][%p] geometry [%d,%d,%d,%d].\n", + data, (pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window"), + (void *) pDrawable, dstX, dstY, dstWidth, dstHeight); + #endif + + /* + * If the display is down and there is not an + * nxagent attached, sleep for a while but + * still give a chance to the client to write + * to the framebuffer. + */ + + length = nxagentImageLength(dstWidth, dstHeight, format, leftPad, depth); + + if (nxagentShadowCounter == 0 && + NXDisplayError(nxagentDisplay) == 1) + { + int us; + + us = IMAGE_DELAY_IF_DOWN * (length / 1024); + + us = (us < 10000 ? 10000 : (us > 1000000 ? 1000000 : us)); + + #ifdef DEBUG + fprintf(stderr, "nxagentPutImage: Sleeping for [%d] milliseconds with length [%d] and link down.\n", + us / 1000, length); + #endif + + usleep(us); + } + + /* + * This is of little use because clients usually write + * to windows only after an expose event, and, in the + * rare case they use a direct put image to the window + * (for a media player it should be a necessity), they + * are likely to monitor the visibility of the window. + */ + + if (nxagentOption(IgnoreVisibility) == 0 && pDrawable -> type == DRAWABLE_WINDOW && + (nxagentWindowIsVisible((WindowPtr) pDrawable) == 0 || + (nxagentDefaultWindowIsVisible() == 0 && nxagentCompositeEnable == 0))) + { + + #ifdef TEST + fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on fully obscured " + "window at [%p].\n", (void *) pDrawable); + #endif + + goto nxagentPutImageEnd; + } + + /* + * This is more interesting. Check if the operation + * will produce a visible result based on the clip + * list of the window and the GC. + */ + + pRegion = nxagentCreateRegion(pDrawable, pGC, dstX, dstY, dstWidth, dstHeight); + + if (REGION_NIL(pRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on fully clipped " + "region [%d,%d,%d,%d] for drawable at [%p].\n", pRegion -> extents.x1, + pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2, + (void *) pDrawable); + #endif + + goto nxagentPutImageEnd; + } + +/* +FIXME: Should use these. + + int framebuffer = 1; + int realize = 1; +*/ + if (nxagentGCTrap == 1 && nxagentReconnectTrap == 0 && + nxagentFBTrap == 0 && nxagentShmTrap == 0) + { + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + fbPutImage(nxagentVirtualDrawable(pDrawable), pGC, depth, + dstX, dstY, dstWidth, dstHeight, leftPad, format, data); + } + else + { + fbPutImage(pDrawable, pGC, depth, + dstX, dstY, dstWidth, dstHeight, leftPad, format, data); + } + + goto nxagentPutImageEnd; + } + + if (nxagentReconnectTrap == 0 && + nxagentSplitTrap == 0) + { + if (pDrawable -> type == DRAWABLE_PIXMAP && + nxagentFBTrap == 0 && nxagentShmTrap == 0) + { + fbPutImage(nxagentVirtualDrawable(pDrawable), pGC, depth, + dstX, dstY, dstWidth, dstHeight, leftPad, format, data); + } + else if (pDrawable -> type == DRAWABLE_WINDOW) + { + fbPutImage(pDrawable, pGC, depth, + dstX, dstY, dstWidth, dstHeight, leftPad, format, data); + } + } + + /* + * We are going to realize the operation + * on the real display. Let's check if + * the link is down. + */ + + if (NXDisplayError(nxagentDisplay) == 1) + { + goto nxagentPutImageEnd; + } + + /* + * Mark the region as corrupted and skip the operation + * if we went out of bandwidth. The drawable will be + * synchronized at later time. Don't do that if the + * image is likely to be a shape or a clip mask, if we + * are here because we are actually synchronizing the + * drawable or if the drawable's corrupted region is + * over-age. + */ + + if (NXAGENT_SHOULD_DEFER_PUTIMAGE(pDrawable)) + { + if (pDrawable -> type == DRAWABLE_PIXMAP && + pDrawable -> depth != 1 && + nxagentOption(DeferLevel) >= 1) + { + #ifdef TEST + fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on region [%d,%d,%d,%d] " + "for drawable at [%p] with drawable pixmap.\n", pRegion -> extents.x1, + pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2, + (void *) pDrawable); + #endif + + nxagentMarkCorruptedRegion(pDrawable, pRegion); + + goto nxagentPutImageEnd; + } + + if (pDrawable -> type == DRAWABLE_WINDOW && + nxagentOption(DeferLevel) >= 2) + { + #ifdef TEST + fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on region [%d,%d,%d,%d] " + "for drawable at [%p] with drawable window.\n", pRegion -> extents.x1, + pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2, + (void *) pDrawable); + #endif + + nxagentMarkCorruptedRegion(pDrawable, pRegion); + + goto nxagentPutImageEnd; + } + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentPutImage: Operation on drawable [%p] not skipped with nxagentSplitTrap [%d].\n", + (void *) pDrawable, nxagentSplitTrap); + } + #endif + + /* + * Check whether we need to enclose the + * image in a split sequence. + */ +/* +FIXME: Should we disable the split with link LAN? + + split = (nxagentOption(Streaming) == 1 && + nxagentOption(LinkType) != LINK_TYPE_NONE && + nxagentOption(LinkType) != LINK_TYPE_LAN +*/ + split = (nxagentOption(Streaming) == 1 && + nxagentOption(LinkType) != LINK_TYPE_NONE +/* +FIXME: Do we stream the images from GLX or Xv? If we do that, + we should also write on the frame buffer, including the + images put on windows, to be able to reconstruct the + region that is out of sync. Surely we should not try to + cache the GLX and Xv images in memory or save them in + the image cache on disk. +*/ +/* +FIXME: Temporarily stream the GLX data. + + && nxagentGlxTrap == 0 + && nxagentXvTrap == 0 +*/ +); + + /* + * Never split images whose depth + * is less than 15. + */ + + if (split == 1 && (nxagentSplitTrap == 1 || depth < 15)) + { + #ifdef TEST + + if (nxagentSplitTrap == 1 || + nxagentReconnectTrap == 1) + { + fprintf(stderr, "nxagentPutImage: Not splitting with reconnection [%d] trap [%d] " + "depth [%d].\n", nxagentSplitTrap, nxagentReconnectTrap, depth); + } + + #endif + + split = 0; + } + #ifdef TEST + else if (split == 1) + { + fprintf(stderr, "nxagentPutImage: Splitting with reconnection [%d] trap [%d] " + "depth [%d].\n", nxagentSplitTrap, nxagentReconnectTrap, depth); + } + #endif + + #ifdef TEST + + if (split == 1) + { + fprintf(stderr, "nxagentPutImage: Splitting the image with size [%d] " + "link [%d] GLX [%d] Xv [%d].\n", length, nxagentOption(LinkType), + nxagentGlxTrap, nxagentXvTrap); + } + else if (nxagentOption(LinkType) != LINK_TYPE_NONE) + { + fprintf(stderr, "nxagentPutImage: Not splitting the image with size [%d] " + "link [%d] GLX [%d] Xv [%d].\n", length, nxagentOption(LinkType), + nxagentGlxTrap, nxagentXvTrap); + } + + #endif + + /* + * If the image was originated by a GLX + * or Xvideo request, temporarily disable + * the use of the cache. + */ + + if (nxagentOption(LinkType) != LINK_TYPE_NONE && + (nxagentGlxTrap == 1 || nxagentXvTrap == 1)) + { + #ifdef TEST + fprintf(stderr, "nxagentPutImage: Disabling the use of the cache with GLX or Xvideo.\n"); + #endif + + NXSetCacheParameters(nxagentDisplay, 0, 1, 0, 0); + + cache = 0; + } + + /* + * Enclose the next messages in a split + * sequence. The proxy will tell us if + * the split took place. + */ + + if (split == 1) + { + /* + * If the drawable is already being split, + * expand the region. Currently drawables + * can't have more than a single split + * region. + */ + + if (nxagentSplitResource(pDrawable) != NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentPutImage: WARNING! Expanding the region with drawable at [%p] streaming.\n", + (void *) pDrawable); + #endif +/* +FIXME: Should probably intersect the region with + the region being split to also invalidate + the commits. +*/ + nxagentMarkCorruptedRegion(pDrawable, pRegion); + + goto nxagentPutImageEnd; + } + else + { + /* + * Assign a new resource to the drawable. + * Will also assign the GC to use for the + * operation. + */ + + resource = nxagentCreateSplit(pDrawable, &pGC); + + #ifdef TEST + fprintf(stderr, "nxagentPutImage: Resource [%d] assigned to drawable at [%p].\n", + resource, (void *) pDrawable); + #endif + } + + NXStartSplit(nxagentDisplay, resource, NXSplitModeDefault); + } + + nxagentRealizeImage(pDrawable, pGC, depth, dstX, dstY, + dstWidth, dstHeight, leftPad, format, data); + + if (split == 1) + { + NXEndSplit(nxagentDisplay, resource); + + /* + * Now we need to check if all the messages went + * straight through the output stream or any of + * them required a split. If no split will take + * place, we will remove the association with the + * drawable and release the resource at the time + * we will handle the no-split event. + */ + + split = nxagentWaitSplitEvent(resource); + + if (split == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentPutImage: Marking corrupted region [%d,%d,%d,%d] for drawable at [%p].\n", + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, + pRegion -> extents.y2, (void *) pDrawable); + #endif + + /* + * Marking the corrupted region we will check + * if the region intersects the split region, + * therefore the split region must be added + * later. + */ + + nxagentMarkCorruptedRegion(pDrawable, pRegion); + + /* + * Assign the region to the drawable. + */ + + nxagentRegionSplit(pDrawable, pRegion); + + pRegion = NullRegion; + } + } + + /* + * The split value could be changed by a + * no-split event in the block above, so + * here we have to check the value again. + */ + + if (split == 0) + { + if (nxagentDrawableStatus(pDrawable) == NotSynchronized) + { + /* + * We just covered the drawable with + * a solid image. We can consider the + * overlapping region as synchronized. + */ + + #ifdef TEST + fprintf(stderr, "nxagentPutImage: Marking synchronized region [%d,%d,%d,%d] for drawable at [%p].\n", + pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, + pRegion -> extents.y2, (void *) pDrawable); + #endif + + nxagentUnmarkCorruptedRegion(pDrawable, pRegion); + } + } + +nxagentPutImageEnd: + + /* + * Check if we disabled caching. + */ + + if (cache == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentPutImage: Reenabling the use of the cache.\n"); + #endif + + NXSetCacheParameters(nxagentDisplay, 1, 1, 1, 1); + } + + if (pRegion != NullRegion) + { + nxagentFreeRegion(pDrawable, pRegion); + } +} + +void nxagentRealizeImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, + int format, char *data) +{ + int length; + + int bytesPerLine; + int numSubImages; + int totalHeight; + + const int subSize = (MAX_REQUEST_SIZE << 2) - sizeof(xPutImageReq); + + Visual *pVisual = NULL; + + RegionPtr clipRegion = NullRegion; + + XImage *image = NULL; + + + if (NXDisplayError(nxagentDisplay) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentRealizeImage: Returning on display error.\n"); + #endif + + goto nxagentRealizeImageEnd; + } + + /* + * Get the visual according to the + * drawable and depth. + */ + + pVisual = nxagentImageVisual(pDrawable, depth); + + if (pVisual == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentRealizeImage: WARNING! Visual not found. Using default visual.\n"); + #endif + + pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual; + } + + /* + * Get bytes per line according to format. + */ + + bytesPerLine = nxagentImagePad(w, format, leftPad, depth); + + if (nxagentOption(Shadow) == 1 && format == ZPixmap && + (nxagentOption(XRatio) != DONT_SCALE || + nxagentOption(YRatio) != DONT_SCALE) && + pDrawable == (DrawablePtr) nxagentShadowPixmapPtr) + { + int scaledx; + int scaledy; + + image = XCreateImage(nxagentDisplay, pVisual, depth, ZPixmap, + 0, data, w, h, BitmapPad(nxagentDisplay), bytesPerLine); + + if (image != NULL) + { + image -> byte_order = IMAGE_BYTE_ORDER; + + image -> bitmap_bit_order = BITMAP_BIT_ORDER; + + nxagentScaleImage(x, y, nxagentOption(XRatio), nxagentOption(YRatio), + &image, &scaledx, &scaledy); + + x = scaledx; + y = scaledy; + + w = image -> width; + h = image -> height; + + data = image -> data; + + /* + * Width of image has changed. + */ + + bytesPerLine = nxagentImagePad(w, format, leftPad, depth); + } + #ifdef WARNING + else + { + fprintf(stderr, "nxagentRealizeImage: Failed to create XImage for scaling.\n"); + } + #endif + } + + if (w == 0 || h == 0) + { + goto nxagentRealizeImageEnd; + } + + totalHeight = h; + + length = bytesPerLine * h; + + h = (subSize < length ? subSize : length) / bytesPerLine; + + numSubImages = totalHeight / h + 1; + + while (numSubImages > 0) + { + if (pDrawable -> type == DRAWABLE_WINDOW) + { + clipRegion = nxagentCreateRegion(pDrawable, pGC, x, y, w, h); + } + + if (clipRegion == NullRegion || REGION_NIL(clipRegion) == 0) + { + nxagentPutSubImage(pDrawable, pGC, depth, x, y, w, h, + leftPad, format, data, pVisual); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentRealizeImage: Skipping the put sub image with geometry " + "[%d,%d,%d,%d] on hidden window at [%p].\n", x, y, w, h, (void *) pDrawable); + } + #endif + + if (clipRegion != NullRegion) + { + nxagentFreeRegion(pDrawable, clipRegion); + } + + y += h; + + data += h * bytesPerLine; + + if (--numSubImages == 1) + { + h = totalHeight % h; + + if (h == 0) + { + break; + } + } + } + +nxagentRealizeImageEnd: + + if (image != NULL) + { + XDestroyImage(image); + } +} + +void nxagentPutSubImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *data, Visual *pVisual) +{ + NXPackedImage *packedImage = NULL; + XImage *plainImage = NULL; + unsigned char *packedChecksum = NULL; + + unsigned int packMethod = nxagentPackMethod; + unsigned int packQuality = nxagentPackQuality; + + ClientPtr client; + + int lossless = 0; + int clean = 0; + int pack = 0; + + /* + * XCreateImage is the place where the leftPad should be passed. + * The image data is received from our client unmodified. In + * theory what we would need to do is just creating an appropri- + * ate XImage structure based on the incoming data and let Xlib + * do the rest. Probably we don't have to pass leftPad again in + * the src_x of XPutImage otherwise the src_x would make Xlib + * to take into account the xoffset field twice. Unfortunately + * passing the leftPad doesn't work. + * + * plainImage = XCreateImage(nxagentDisplay, pVisual, + * depth, format, leftPad, data, + * w, h, BitmapPad(nxagentDisplay), + * nxagentImagePad(w, format, leftPad, depth)); + */ + + if ((plainImage = XCreateImage(nxagentDisplay, pVisual, + depth, format, leftPad, data, + w, h, BitmapPad(nxagentDisplay), + nxagentImagePad(w, format, leftPad, depth))) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentPutSubImage: WARNING! Failed to create image.\n"); + #endif + + goto nxagentPutSubImageEnd; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentPutSubImage: Handling image with geometry [%d,%d] depth [%d].\n", + w, h, depth); + + fprintf(stderr, "nxagentPutSubImage: Default pack method is [%d] quality is [%d].\n", + packMethod, packQuality); + #endif + +/* +FIXME: Should use an unpack resource here. +*/ + client = requestingClient; + + if (client == NULL) + { + client = serverClient; + + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: WARNING! Using the server client with index [%d].\n", + client -> index); + #endif + } + + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: Server order is [%d] client order is [%d].\n", + nxagentServerOrder(), nxagentClientOrder(client)); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: Display image order is [%d] bitmap order is [%d].\n", + ImageByteOrder(nxagentDisplay), BitmapBitOrder(nxagentDisplay)); + #endif + + /* + * We got the image data from the X client or + * from the frame-buffer with our own endianess. + * Byte swap the image data if the display has + * a different endianess than our own. + */ + + if (nxagentImageNormalize(plainImage) != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: WARNING! Reformatted the image with remote order [%d/%d].\n", + plainImage -> byte_order, plainImage -> bitmap_bit_order); + #endif + } + + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: Image has visual with RGB color masks [%0lx][%0lx][%0lx].\n", + pVisual -> red_mask, pVisual -> green_mask, pVisual -> blue_mask); + #endif + + /* + * Check if the user requested to pack the + * image but don't pack it if we are not + * connected to a proxy or if the depth is + * less than 15 bpp. + */ + + pack = (nxagentOption(LinkType) != LINK_TYPE_NONE && + packMethod != PACK_NONE && depth > 8); + + lossless = (packMethod == nxagentPackLossless); + + if (pack == 1 && lossless == 0) + { + /* + * Force the image to be sent as a plain + * bitmap if we don't have any lossless + * encoder available. + */ + + if (w <= IMAGE_PACK_WIDTH || h <= IMAGE_PACK_HEIGHT || + nxagentImageLength(w, h, format, leftPad, depth) <= + IMAGE_PACK_LENGTH || nxagentLosslessTrap == 1) + { + if (nxagentPackLossless == PACK_NONE) + { + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: Disabling pack with lossless method [%d] " + "trap [%d] size [%d].\n", nxagentPackLossless, nxagentLosslessTrap, + nxagentImageLength(w, h, format, leftPad, depth)); + #endif + + pack = 0; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: Lossless encoder with geometry [%d,%d] " + "trap [%d] size [%d].\n", w, h, nxagentLosslessTrap, + nxagentImageLength(w, h, format, leftPad, depth)); + #endif + + packMethod = nxagentPackLossless; + + lossless = 1; + } + } + } + + /* + * Do we still want to pack the image? + */ + + if (pack == 1) + { + /* + * Set the geometry and alpha channel + * to be used for the unpacked image. + */ + + if (nxagentUnpackVisualId[client -> index] != pVisual -> visualid) + { + nxagentUnpackVisualId[client -> index] = pVisual -> visualid; + + #ifdef DEBUG + fprintf(stderr, "nxagentPutSubImage: Sending new geometry for client [%d].\n", + client -> index); + #endif + + NXSetUnpackGeometry(nxagentDisplay, client -> index, pVisual); + } + + /* + * Check if the image is supposed to carry + * the alpha data in the fourth byte and, + * if so, send the alpha channel using the + * specific encoding. + */ + + if (plainImage -> depth == 32) + { + nxagentSetUnpackAlpha(pDrawable, plainImage, client); + } + + /* + * If the image doesn't come from the XVideo or the + * GLX extension try to locate it in the cache. The + * case of the lossless trap is also special, as we + * want to eventually encode the image again using + * a lossless compression. + */ +/* +FIXME: Should try to locate the image anyway, if the lossless + trap is set, and if the image was encoded by a lossy + compressor, roll back the changes and encode the image + again using the preferred method. +*/ + if (nxagentNeedCache(plainImage, packMethod) && + nxagentGlxTrap == 0 && nxagentXvTrap == 0 && + nxagentLosslessTrap == 0 && NXImageCacheSize > 0) + { + /* + * Be sure that the padding bits are + * cleaned before calculating the MD5 + * checksum. + */ +/* +FIXME: There should be a callback registered by the agent that + provides a statistics report, in text format, telling + for example how many images were searched in the cache, + how many were found, how many drawables are to be synch- + ronized, etc. This statistics report would be included + by the proxy in its stat output. +*/ + clean = 1; + + NXCleanImage(plainImage); + + /* + * Will return a pointer to the image and checksum + * taken from the cache, if found. If the image is + * not found, the function returns a null image and + * a pointer to the calculated checksum. It is up + * to the application to free the memory. We will + * use the checksum to add the image in the cache. + */ + + packedImage = NXCacheFindImage(plainImage, &packMethod, &packedChecksum); + + nxagentImageStatistics.partialLookups++; + nxagentImageStatistics.totalLookups++; + + if (packedImage != NULL) + { + #ifdef DEBUG + fprintf(stderr, "nxagentPutSubImage: Matched image of geometry [%d,%d] data size [%d] in cache.\n", + w, h, packedImage -> xoffset); + #endif + + NXPutPackedImage(nxagentDisplay, client -> index, nxagentDrawable(pDrawable), + nxagentGC(pGC), packedImage, packMethod, depth, + 0, 0, x, y, w, h); + + nxagentImageStatistics.partialMatches++; + nxagentImageStatistics.totalMatches++; + + packedChecksum = NULL; + packedImage = NULL; + + goto nxagentPutSubImageEnd; + } + #ifdef DEBUG + else + { + fprintf(stderr, "nxagentPutSubImage: WARNING! Missed image of geometry [%d,%d] in cache.\n", + w, h); + } + #endif + } + + /* + * If a specific encoder was not mandated, + * try to guess if a lossless encoder will + * compress better. + */ + + if (lossless == 0 && nxagentOption(Adaptive) == 1) + { + int ratio = nxagentUniquePixels(plainImage); + + if (ratio <= IMAGE_UNIQUE_RATIO) + { + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: Lossless encoder with geometry [%d,%d] ratio [%d%%].\n", + w, h, ratio); + #endif + + packMethod = nxagentPackLossless; + + lossless = 1; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentPutSubImage: Default encoder with geometry [%d,%d] ratio [%d%%].\n", + w, h, ratio); + } + #endif + } + + /* + * Encode the image using the selected + * pack method. + */ + + if (packMethod == PACK_RLE_16M_COLORS || + packMethod == PACK_RGB_16M_COLORS || + packMethod == PACK_BITMAP_16M_COLORS) + { + /* + * Cleanup the image if we didn't do that yet. + * We assume that the JPEG and PNG compression + * methods will actually ignore the padding + * bytes. In other words, bitmap images prod- + * ucing the same visual output should produce + * compressed images that are bitwise the same + * regardless the padding bits. + */ + + if (clean == 0) + { + if (nxagentNeedClean(plainImage, packMethod) == 1) + { + clean = 1; + + NXCleanImage(plainImage); + } + } + + switch (packMethod) + { + /* + * If nothing is done by the bitmap encoder, + * it saves an allocation and a memory copy + * by setting the data field of the packed + * image to the original data. We need to + * check this at the time we will free the + * packed image. + */ + + case PACK_BITMAP_16M_COLORS: + { + packedImage = NXEncodeBitmap(plainImage, packMethod, packQuality); + + break; + } + case PACK_RGB_16M_COLORS: + { + packedImage = NXEncodeRgb(plainImage, packMethod, packQuality); + + break; + } + default: + { + packedImage = NXEncodeRle(plainImage, packMethod, packQuality); + + break; + } + } + } + else if (packMethod >= PACK_JPEG_8_COLORS && + packMethod <= PACK_JPEG_16M_COLORS) + { + packedImage = NXEncodeJpeg(plainImage, packMethod, packQuality); + } + else if (packMethod >= PACK_PNG_8_COLORS && + packMethod <= PACK_PNG_16M_COLORS) + { + packedImage = NXEncodePng(plainImage, packMethod, packQuality); + } + else if (packMethod != PACK_NONE) + { + #ifdef WARNING + fprintf(stderr, "nxagentPutSubImage: WARNING! Ignoring deprecated pack method [%d].\n", + packMethod); + #endif + + packMethod = PACK_NONE; + } + } + + /* + * If we didn't produce a valid packed + * image, send the image as a X bitmap. + */ + + if (packedImage != NULL) + { + nxagentImageStatistics.partialEncoded++; + nxagentImageStatistics.totalEncoded++; + + #ifdef DEBUG + fprintf(stderr, "nxagentPutSubImage: Using packed image with method [%d] quality [%d] " + "geometry [%d,%d] data size [%d].\n", packMethod, packQuality, + w, h, packedImage -> xoffset); + #endif + + NXPutPackedImage(nxagentDisplay, client -> index, nxagentDrawable(pDrawable), + nxagentGC(pGC), packedImage, packMethod, depth, + 0, 0, x, y, w, h); + + /* + * Add the image only if we have a valid + * checksum. This is the case only if we + * originally tried to find the image in + * cache. + */ + + if (NXImageCacheSize > 0 && packedChecksum != NULL) + { + #ifdef DEBUG + fprintf(stderr, "nxagentPutSubImage: Adding image with geometry [%d,%d] data size [%d] " + "to the cache.\n", w, h, packedImage -> xoffset); + #endif + + /* + * Check if both the plain and the packed + * image point to the same data. In this + * case we need a copy. + */ + + if (packedImage -> data == plainImage -> data && + nxagentImageCopy(plainImage, packedImage) == NULL) + { + goto nxagentPutSubImageEnd; + } + + NXCacheAddImage(packedImage, packMethod, packedChecksum); + + nxagentImageStatistics.partialAdded++; + nxagentImageStatistics.totalAdded++; + + packedChecksum = NULL; + packedImage = NULL; + } + } + else + { + /* + * Clean the image to help the proxy to match + * the checksum in its cache. Do that only if + * the differential compression is enabled and + * if the image is not supposed to carry the + * alpha data in the fourth byte of the pixel. + */ +/* +FIXME: If we failed to encode the image by any of the available + methods, for example if we couldn't allocate memory, we + may need to ripristinate the alpha channel, that in the + meanwhile was sent in the unpack alpha message. This can + be done here, if the clean flag is true and we are going + to send a plain image. +*/ + if (clean == 0) + { + clean = (nxagentOption(LinkType) != LINK_TYPE_NONE && + nxagentOption(LinkType) != LINK_TYPE_LAN && depth != 32); + + if (clean == 1) + { + #ifdef DEBUG + fprintf(stderr, "nxagentPutSubImage: Cleaning the image with link type [%d] and depth [%d].\n", + nxagentOption(LinkType), depth); + #endif + + NXCleanImage(plainImage); + } + #ifdef DEBUG + else + { + fprintf(stderr, "nxagentPutSubImage: Not cleaning the image with link type [%d] and depth [%d].\n", + nxagentOption(LinkType), depth); + } + #endif + } + + #ifdef DEBUG + fprintf(stderr, "nxagentPutSubImage: Calling XPutImage with geometry [%d,%d] and data size [%d].\n", + w, h, plainImage -> bytes_per_line * plainImage -> height); + #endif + + /* + * Passing the leftPad value in src_x doesn't work. + * + * XPutImage(nxagentDisplay, nxagentDrawable(pDrawable), + * nxagentGC(pGC), plainImage, leftPad, 0, x, y, w, h); + */ + + XPutImage(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), plainImage, 0, 0, x, y, w, h); + } + +nxagentPutSubImageEnd: + + #ifdef TEST + fprintf(stderr, "nxagentPutSubImage: Performed [%.0f] lookups in the cache with [%.0f] matches.\n", + nxagentImageStatistics.totalLookups, nxagentImageStatistics.totalMatches); + + fprintf(stderr, "nxagentPutSubImage: Encoded [%.0f] images with [%.0f] added to the cache.\n", + nxagentImageStatistics.totalEncoded, nxagentImageStatistics.totalAdded); + #endif + + if (packedChecksum != NULL) + { + Xfree(packedChecksum); + } + + if (packedImage != NULL) + { + if (packedImage -> data != NULL && + packedImage -> data != plainImage -> data) + { + Xfree(packedImage -> data); + } + + Xfree(packedImage); + } + + Xfree(plainImage); +} + +void nxagentGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *data) +{ + #ifdef TEST + fprintf(stderr, "nxagentGetImage: Called with drawable at [%p] geometry [%d,%d,%d,%d].\n", + (void *) pDrawable, x, y, w, h); + + fprintf(stderr, "nxagentGetImage: Format is [%d] plane mask is [%lx].\n", + format, planeMask); + #endif + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentGetImage: Going to get image from virtual pixmap at [%p].\n", + (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbGetImage(nxagentVirtualDrawable(pDrawable), x, y, w, h, format, planeMask, data); + } + else + { + fbGetImage(pDrawable, x, y, w, h, format, planeMask, data); + } +} + +/* + * We have to reset the visual cache before + * connecting to another display, so that a + * new unpack geometry can be communicated + * to the new proxy. + */ + +void nxagentResetVisualCache() +{ + int i; + + for (i = 0; i < MAX_CONNECTIONS; i++) + { + nxagentUnpackVisualId[i] = None; + } +} + +void nxagentResetAlphaCache() +{ + int i; + + for (i = 0; i < MAX_CONNECTIONS; i++) + { + if (nxagentUnpackAlpha[i]) + { + Xfree(nxagentUnpackAlpha[i] -> data); + + Xfree(nxagentUnpackAlpha[i]); + + nxagentUnpackAlpha[i] = NULL; + } + } +} + +int nxagentScaleImage(int x, int y, unsigned xRatio, unsigned yRatio, + XImage **pImage, int *scaledx, int *scaledy) +{ + int x1; + int x2; + int y1; + int y2; + + int xx1; + int xx2; + int yy1; + int yy2; + + int newWidth; + int newHeight; + + int i; + int j; + int k; + int l; + + unsigned long val; + + XImage *newImage; + XImage *image = *pImage; + + #ifdef FAST_GET_PUT_PIXEL + + register char *srcPixel; + register char *dstPixel; + + int i; + + #endif + + if (image == NULL) + { + return 0; + } + + x1 = (xRatio * x) >> PRECISION; + x2 = (xRatio * (x + image -> width)) >> PRECISION; + + y1 = (yRatio * y) >> PRECISION; + y2 = (yRatio * (y + image -> height)) >> PRECISION; + + newWidth = x2 - x1; + newHeight = y2 - y1; + + newImage = XCreateImage(nxagentDisplay, NULL, image -> depth, image -> format, 0, NULL, + newWidth, newHeight, BitmapPad(nxagentDisplay), + PixmapBytePad(newWidth, image -> depth)); + + if (newImage == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentScaleImage: PANIC! Failed to create the target image.\n"); + #endif + + return 0; + } + + newImage -> red_mask = image -> red_mask; + newImage -> green_mask = image -> green_mask; + newImage -> blue_mask = image -> blue_mask; + + newImage -> byte_order = IMAGE_BYTE_ORDER; + newImage -> bitmap_bit_order = BITMAP_BIT_ORDER; + + newImage -> data = Xmalloc(newImage -> bytes_per_line * newHeight); + + if (newImage -> data == NULL) + { + Xfree(newImage); + + #ifdef PANIC + fprintf(stderr, "nxagentScaleImage: PANIC! Failed to create the target image data.\n"); + #endif + + return 0; + } + + newImage -> width = newWidth; + newImage -> height = newHeight; + + for (j = y; j < y + image -> height; j++) + { + yy1 = (yRatio * j) >> PRECISION; + yy2 = (yRatio * (j + 1)) >> PRECISION; + + for (i = x; i < x + image -> width; i++) + { + #ifndef FAST_GET_PUT_PIXEL + + val = XGetPixel(image, i - x, j - y); + + #else + + srcPixel = &image -> data[(j * image -> bytes_per_line) + + ((i * image -> bits_per_pixel) >> 3)]; + + dstPixel = (char *) &val; + + val = 0; + + for (i = (image -> bits_per_pixel + 7) >> 3; --i >= 0; ) + { + *dstPixel++ = *srcPixel++; + } + + #endif + + xx1 = (xRatio * i) >> PRECISION; + xx2 = (xRatio * (i + 1)) >> PRECISION; + + for (l = yy1; l < yy2; l++) + { + for (k = xx1; k < xx2; k++) + { + #ifndef FAST_GET_PUT_PIXEL + + XPutPixel(newImage, k - x1, l - y1, val); + + #else + + dstPixel = &newImage -> data[((l - y1) * newImage -> bytes_per_line) + + (((k - x1) * newImage -> bits_per_pixel) >> 3)]; + + srcPixel = (char *) &val; + + for (i = (newImage -> bits_per_pixel + 7) >> 3; --i >= 0; ) + { + *dstPixel++ = *srcPixel++; + } + + #endif + } + } + } + } + + if (image -> obdata != NULL) + { + Xfree((char *) image -> obdata); + } + + Xfree((char *) image); + + *pImage = newImage; + + *scaledx = x1; + *scaledy = y1; + + return 1; +} + +char *nxagentAllocateImageData(int width, int height, int depth, int *length, int *format) +{ + char *data; + + int leftPad; + + leftPad = 0; + + *format = (depth == 1) ? XYPixmap : ZPixmap; + + *length = nxagentImageLength(width, height, *format, leftPad, depth); + + data = NULL; + + if ((data = xalloc(*length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentAllocateImageData: WARNING! Failed to allocate [%d] bytes of memory.\n", *length); + #endif + } + + return data; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Image.h b/nx-X11/programs/Xserver/hw/nxagent/Image.h new file mode 100644 index 000000000..fb77f3c80 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Image.h @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Image_H__ +#define __Image_H__ + +/* + * Graphic operations. + */ + +void nxagentPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int dstX, int dstY, int dstWidth, int dstHeight, + int leftPad, int format, char *data); + +void nxagentRealizeImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, + int format, char *data); + +void nxagentPutSubImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *data, Visual *pVisual); + +void nxagentGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *data); + +/* + * Pack and split parameters we get + * from the NX transport. + */ + +extern int nxagentPackLossless; +extern int nxagentPackMethod; +extern int nxagentPackQuality; +extern int nxagentSplitThreshold; + +/* + * Set if images can use the alpha + * channel and if the alpha channel + * can be sent in compressed form. + */ + +extern int nxagentAlphaEnabled; +extern int nxagentAlphaCompat; + +/* + * Reset the visual and alpha cache + * before closing the screen or con- + * necting to a different display. + */ + +void nxagentResetVisualCache(void); +void nxagentResetAlphaCache(void); + +/* + * Always use the default visual for the + * image related functions. + */ + +#define nxagentImageVisual(pDrawable, depth) \ + ((depth) == 32 ? &nxagentAlphaVisual : \ + nxagentDefaultVisual(((pDrawable) -> pScreen))) + +/* + * Byte swap the image if the display + * uses a different endianess. + */ + +#define nxagentImageNormalize(image) \ + ((image) -> byte_order != IMAGE_BYTE_ORDER || \ + (image) -> bitmap_bit_order != BITMAP_BIT_ORDER ? \ + nxagentImageReformat((image) -> data, (image) -> bytes_per_line * \ + (image) -> height * ((image) -> format == XYPixmap ? (image) -> depth : 1), \ + ((image) -> format == ZPixmap ? \ + BitsPerPixel((image) -> depth) : 1), \ + (image) -> byte_order) : 0) + +/* + * Other image related functions. + */ + +int nxagentImageLength(int width, int height, int format, int leftPad, int depth); + +int nxagentImagePad(int width, int format, int leftPad, int depth); + +int nxagentImageReformat(char *base, int nbytes, int bpp, int order); + +void nxagentImageStatisticsHandler(char **buffer, int type); + +int nxagentScaleImage(int x, int y, unsigned xRatio, unsigned yRatio, XImage **pImage, int *scaledx, int *scaledy); + +char *nxagentAllocateImageData(int width, int height, int depth, int *length, int *format); + +#endif /* __Image_H__ */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Imakefile b/nx-X11/programs/Xserver/hw/nxagent/Imakefile new file mode 100644 index 000000000..804f95f78 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Imakefile @@ -0,0 +1,220 @@ +# XCOMM $Xorg: Imakefile,v 1.3 2000/08/17 19:53:28 cpqbld Exp $ + +#include + +#ifdef OS2Architecture +SRCS1 = os2Stub.c +OBJS1 = os2Stub.o +#endif + +SRCS = NXrandr.c \ + NXwindow.c \ + NXevents.c \ + NXproperty.c \ + NXdixfonts.c \ + NXglyphcurs.c \ + NXdispatch.c \ + NXrender.c \ + NXglyph.c \ + NXpicture.c \ + NXextension.c \ + NXshm.c \ + NXglxext.c \ + NXxvdisp.c \ + NXmiglyph.c \ + NXmiexpose.c \ + NXresource.c \ + NXmiwindow.c \ + NXxrandr.c \ + NXdamage.c \ + NXmitrap.c \ + Args.c \ + Binder.c \ + Colormap.c \ + Cursor.c \ + Dialog.c \ + Display.c \ + Events.c \ + Font.c \ + GC.c \ + GCOps.c \ + Millis.c \ + Handlers.c \ + Init.c \ + Keyboard.c \ + Keystroke.c \ + Pointer.c \ + Screen.c \ + TestExt.c \ + Visual.c \ + Drawable.c \ + Window.c \ + Pixmap.c \ + Render.c \ + Client.c \ + Rootless.c \ + Extensions.c \ + Options.c \ + Clipboard.c \ + Splash.c \ + Split.c \ + Holder.c \ + Reconnect.c \ + Error.c \ + Atoms.c \ + Trap.c \ + Image.c \ + Composite.c \ + Pixels.c \ + stubs.c \ + miinitext.c \ + $(SRCS1) + +OBJS = NXrandr.o \ + NXwindow.o \ + NXevents.o \ + NXproperty.o \ + NXdixfonts.o \ + NXglyphcurs.o \ + NXdispatch.o \ + NXrender.o \ + NXglyph.o \ + NXpicture.o \ + NXextension.o \ + NXshm.o \ + NXglxext.o \ + NXxvdisp.o \ + NXmiglyph.o \ + NXmiexpose.o \ + NXresource.o \ + NXmiwindow.o \ + NXxrandr.o \ + NXdamage.o \ + NXmitrap.o \ + Args.o \ + Binder.o \ + Colormap.o \ + Cursor.o \ + Dialog.o \ + Display.o \ + Events.o \ + Font.o \ + GC.o \ + GCOps.o \ + Millis.o \ + Handlers.o \ + Init.o \ + Keyboard.o \ + Keystroke.o \ + Pointer.o \ + Screen.o \ + TestExt.o \ + Visual.o \ + Drawable.o \ + Window.o \ + Pixmap.o \ + Render.o \ + Client.o \ + Rootless.o \ + Extensions.o \ + Options.o \ + Clipboard.o \ + Splash.o \ + Split.o \ + Holder.o \ + Reconnect.o \ + Error.o \ + Atoms.o \ + Trap.o \ + Image.o \ + Composite.o \ + Pixels.o \ + stubs.o \ + miinitext.o \ + $(OBJS1) + +VFBINCLUDES = -I../../fb -I../../mfb -I../../render +NXFONTINCLUDES = -I../../../../lib/font/include +LIBXRANDRINCLUDES= -I../../../../lib/Xrandr + +INCLUDES = -I. -I../../../../../nxcomp -I../../../../../nxcompext -I../../../../../nxcompshad \ + -I../../../../extras/Mesa/include \ + -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ + -I../../mi -I../../include -I../../os \ + -I../../miext/damage -I../../miext/cw \ + -I../../GL/glx -I../../GL/include -I../../../../lib/GL/include -I../../Xext \ + -I$(EXTINCSRC) -I$(XINCLUDESRC) \ + $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES) +#ifdef SunArchitecture +INCLUDES = -I. -I../../../../../nxcomp -I../../../../../nxcompext -I../../../../../nxcompshad \ + -I../../../../extras/Mesa/include \ + -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ + -I/usr/sfw/include \ + -I../../mi -I../../include -I../../os \ + -I../../GL/glx -I../../GL/include -I../../../../lib/GL/include -I../../Xext \ + -I../../miext/damage -I../../miext/cw \ + -I$(EXTINCSRC) -I$(XINCLUDESRC) \ + $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES) +#else +#ifdef cygwinArchitecture +INCLUDES = -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ + -I../../mi -I../../include -I../../os \ + -I../../GL/glx -I../../GL/include -I../../../../lib/GL/include -I../../Xext \ + -I../../miext/damage -I../../miext/cw \ + -I../../../../../nxcomp -I../../../../../nxcompext -I../../../../../nxcompshad \ + -I../../../../extras/Mesa/include \ + -I$(EXTINCSRC) -I$(XINCLUDESRC) \ + $(VFBINCLUDES) $(NXFONTINCLUDES) $(LIBXRANDRINCLUDES) +#endif +#endif + +### NXAGENT Defines: +# +# NXAGENT_FONTCACHE_SIZE Number of cache slots +# NXAGENT_SHAPE Old shape code +# NXAGENT_GLYPHCACHE +# NXAGENT_GLYPHCACHE_SIZE Slots for glyph cache +# NXAGENT_SHAPE2 New shape code +# NXAGENT_FIXKEYS Force the release of pressed key when loosing focus +# NXAGENT_EXPOSURES Manage expose events +# NXAGENT_CLIPBOARD Enables clipboard cut and paste function between X servers. +# NXAGENT_FONTEXCLUDE Exclude some specific font names (only "-ult1mo" at this moment). +# NXAGENT FULLSCREEN Fullscreen mode +# + +#if NXUpgradeAgentServer +UPG_DEFINES=-DNXAGENT_UPGRADE +#else +UPG_DEFINES= +#endif + +DEFINES = -g $(OS_DEFINES) $(EXT_DEFINES) $(UPG_DEFINES) \ + -UXF86VIDMODE -UXFreeXDGA -UXF86MISC -UXF86DRI -UXFree86LOADER \ + -DNXAGENT_SERVER \ + -DNXAGENT_CONSTRAINCURSOR \ + -DNXAGENT_FONTCACHE_SIZE=50 \ + -DNXAGENT_GLYPHCACHE -DNXAGENT_GLYPHCACHE_SIZE=50 \ + -DNXAGENT_SHAPE2 \ + -DNXAGENT_FIXKEYS \ + -DNXAGENT_CLIPBOARD \ + -DNXAGENT_EXPOSURES \ + -DNXAGENT_FONTEXCLUDE \ + -DNXAGENT_PACKEDIMAGES \ + -DNXAGENT_VISIBILITY \ + -DNXAGENT_WAKEUP=1000 \ + -DNXAGENT_ONSTART \ + -DNXAGENT_SPLASH \ + -DNXAGENT_ARTSD \ + -UPANORAMIX + +all:: $(OBJS) + +LinkSourceFile(stubs.c,$(SERVERSRC)/Xi) +SpecialCObjectRule(Init,$(ICONFIGFILES),$(_NOOP_)) +LinkSourceFile(miinitext.c,$(SERVERSRC)/mi) +SpecialCObjectRule(miinitext,$(ICONFIGFILES), $(_NOOP_)) + +NormalLibraryObjectRule() +NormalLibraryTarget(nxagent,$(OBJS)) + +DependTarget() diff --git a/nx-X11/programs/Xserver/hw/nxagent/Init.c b/nx-X11/programs/Xserver/hw/nxagent/Init.c new file mode 100644 index 000000000..197bd8c14 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Init.c @@ -0,0 +1,491 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include +#include +#include + +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "fontstruct.h" + +#include "Agent.h" +#include "Display.h" +#include "Screen.h" +#include "Pointer.h" +#include "Keyboard.h" +#include "Handlers.h" +#include "Init.h" +#include "Args.h" +#include "Client.h" +#include "Options.h" +#include "Drawable.h" +#include "Pixmaps.h" +#include "GCs.h" +#include "Font.h" +#include "Millis.h" +#include "Error.h" + +#include "NX.h" +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +#define NXAGENT_VERSION "3.1.0" + +/* + * ProcVector array defined in tables.c. + */ + +extern int (*ProcVector[256])(ClientPtr); + +/* + * From the fb code. + */ + +extern int fbGCPrivateIndex; + +/* + * Stubs for the DPMS extension. + */ + +#ifdef DPMSExtension + +void DPMSSet(int level); +int DPMSGet(int *level); +Bool DPMSSupported(void); + +#endif + +/* + * Our error logging function. + */ + +void OsVendorVErrorFFunction(const char *f, va_list args); + +/* + * True if this is a fatal error. + */ + +extern int OsVendorVErrorFFatal; + +/* + * Redirect the error output to a + * different file + */ + +extern void (*OsVendorStartRedirectErrorFProc)(); +extern void (*OsVendorEndRedirectErrorFProc)(); + +void OsVendorStartRedirectErrorFFunction(); +void OsVendorEndRedirectErrorFFunction(); + +/* + * Called by InitGlobals() in the + * new X server tree. + */ + +#ifdef NXAGENT_UPGRADE + +void ddxInitGlobals(void) +{ + /* + * Install our error logging function. + */ + + OsVendorVErrorFProc = OsVendorVErrorFFunction; + + OsVendorStartRedirectErrorFProc = OsVendorStartRedirectErrorFFunction; + OsVendorEndRedirectErrorFProc = OsVendorEndRedirectErrorFFunction; +} + +#endif + +/* + * Set if the remote display supports + * backing store. + */ +/* +FIXME: These, if not removed, should at least + be moved to Display.h and Display.c. +*/ +int nxagentBackingStore; +int nxagentSaveUnder; + +/* + * This is true at startup and set to the value of + * nxagentFullGeneration at the end of InitInput. + * + * InitOutput + * nxagentOpenDisplay (if nxagentDoFullGeneration) + * nxagentCloseDisplay (if (nxagentDoFullGeneration && nxagentDisplay)) + * nxagentFree* + * nxagentListRemoteFonts + * AddScreen + * nxagentOpenScreen + * InitInput + */ + +int nxagentDoFullGeneration = 1; + +/* + * Called at X server's initialization. + */ + +void InitOutput(ScreenInfo *screenInfo, int argc, char *argv[]) +{ + char *authority; + int i; + + #ifdef __sun + + char *environment; + + #endif + + /* + * Print our pid and version information. + */ + + if (serverGeneration <= 1) + { + fprintf(stderr, "\nNXAGENT - Version " NXAGENT_VERSION "\n\n"); + fprintf(stderr, "Copyright (C) 2001, 2007 NoMachine.\n"); + fprintf(stderr, "See http://www.nomachine.com/ for more information.\n\n"); + + fprintf(stderr, "Info: Agent running with pid '%d'.\n", getpid()); + + fprintf(stderr, "Session: Starting session at '%s'.\n", GetTimeAsString()); + } + + /* + * Unset the LD_LIBRARY_PATH variable in + * Popen() before calling execl() in the + * child process. + */ + + NXUnsetLibraryPath(1); + + if (nxagentUserDefinedFontPath == 0) + { + #ifdef TEST + fprintf(stderr, "InitOutput: Calling nxagentVerifyDefaultFontPath.\n"); + #endif + + nxagentVerifyDefaultFontPath(); + } + #ifdef TEST + else + { + fprintf(stderr, "InitOutput: User defined font path. Skipping the check on the fonts dir.\n"); + } + #endif + + if ((authority = getenv("NX_XAUTHORITY"))) + { + #ifdef __sun + + environment = malloc(15 + strlen(authority)); + + sprintf(environment, "XAUTHORITY=%s", authority); + + if (putenv(environment) < 0) + + #else + + if (setenv("XAUTHORITY", authority, True) < 0) + + #endif + + { + fprintf(stderr, "Warning: Couldn't set the XAUTHORITY environment to [%s]\n", + authority); + } + } + + nxagentInitBSPixmapList(); + + /* + * Open the display. We are at the early startup and + * the information we'll get from the remote X server + * will mandate some of the characteristics of the + * session, like the screen depth. Note that this re- + * liance on the remote display at session startup + * should be removed. We should always operate at 32 + * bpp, internally, and do the required translations + * as soon as the graphic operation needs to be real- + * ized on the remote display. + */ + + nxagentOpenDisplay(argc, argv); + +/* +FIXME: These variables, if not removed at all because have probably + become useless, should be moved to Display.h and Display.c. +*/ + nxagentBackingStore = XDoesBackingStore(DefaultScreenOfDisplay(nxagentDisplay)); + + #ifdef TEST + fprintf(stderr, "InitOutput: Remote display backing store support [%d].\n", + nxagentBackingStore); + #endif + + nxagentSaveUnder = XDoesSaveUnders(DefaultScreenOfDisplay(nxagentDisplay)); + + #ifdef TEST + fprintf(stderr, "InitOutput: Remote display save under support [%d].\n", + nxagentSaveUnder); + #endif + + /* + * Initialize the basic screen info. + */ + + nxagentSetScreenInfo(screenInfo); + + /* + * Initialize pixmap formats for this screen. + */ + + nxagentSetPixmapFormats(screenInfo); + + /* + * Get our own privates' index. + */ + + nxagentWindowPrivateIndex = AllocateWindowPrivateIndex(); + nxagentGCPrivateIndex = AllocateGCPrivateIndex(); + RT_NX_GC = CreateNewResourceType(nxagentDestroyNewGCResourceType); + nxagentFontPrivateIndex = AllocateFontPrivateIndex(); + RT_NX_FONT = CreateNewResourceType(nxagentDestroyNewFontResourceType); + nxagentClientPrivateIndex = AllocateClientPrivateIndex(); + nxagentPixmapPrivateIndex = AllocatePixmapPrivateIndex(); + RT_NX_PIXMAP = CreateNewResourceType(nxagentDestroyNewPixmapResourceType); + + RT_NX_CORR_BACKGROUND = CreateNewResourceType(nxagentDestroyCorruptedBackgroundResource); + RT_NX_CORR_WINDOW = CreateNewResourceType(nxagentDestroyCorruptedWindowResource); + RT_NX_CORR_PIXMAP = CreateNewResourceType(nxagentDestroyCorruptedPixmapResource); + + fbGCPrivateIndex = AllocateGCPrivateIndex(); + + if (nxagentNumScreens == 0) + { + nxagentNumScreens = 1; + } + + for (i = 0; i < nxagentNumScreens; i++) + { + AddScreen(nxagentOpenScreen, argc, argv); + } + + nxagentNumScreens = screenInfo->numScreens; + + /* + * Initialize the GCs used by the synchro- + * nization put images. We do it here beca- + * use we use the nxagentDefaultScreen. + */ + + nxagentAllocateGraphicContexts(); + + nxagentDoFullGeneration = nxagentFullGeneration; +} + +void InitInput(argc, argv) + int argc; + char *argv[]; +{ + pointer ptr, kbd; + + ptr = AddInputDevice(nxagentPointerProc, True); + kbd = AddInputDevice(nxagentKeyboardProc, True); + + RegisterPointerDevice(ptr); + RegisterKeyboardDevice(kbd); + + mieqInit(kbd, ptr); + + /* + * Add the display descriptor to the + * set of descriptors awaited by the + * dispatcher. + */ + + nxagentAddXConnection(); + + if (nxagentOption(Shadow)) + { + RegisterBlockAndWakeupHandlers(nxagentShadowBlockHandler, nxagentShadowWakeupHandler, NULL); + } + else + { + RegisterBlockAndWakeupHandlers(nxagentBlockHandler, nxagentWakeupHandler, NULL); + } + + /* + * We let the proxy flush the link on our behalf + * after having opened the display. We are now + * entering the dispatcher. From now on we'll + * flush the proxy link explicitly. + */ + + #ifdef TEST + fprintf(stderr, "InitInput: Setting the NX flush policy to deferred.\n"); + #endif + + NXSetDisplayPolicy(nxagentDisplay, NXPolicyDeferred); +} + +/* + * DDX specific abort routine. This is called + * by AbortServer() that, in turn, is called + * by FatalError(). + */ + +void AbortDDX() +{ + nxagentDoFullGeneration = True; + + nxagentCloseDisplay(); + + /* + * Do the required finalization if we + * are not going through the normal + * X server shutdown. + */ + + if ((dispatchException & DE_TERMINATE) == 0) + { + nxagentAbortDisplay(); + } +} + +/* + * Called by GiveUp(). + */ + +void ddxGiveUp() +{ + AbortDDX(); +} + +#ifdef NXAGENT_UPGRADE + +void ddxBeforeReset(void) +{ +} + +#endif + +void OsVendorInit() +{ + return; +} + +void OsVendorFatalError() +{ + /* + * Let the session terminate gracely + * from an user's standpoint. + */ + + fprintf(stderr, "Session: Aborting session at '%s'.\n", GetTimeAsString()); + + fprintf(stderr, "Session: Session aborted at '%s'.\n", GetTimeAsString()); +} + +void OsVendorVErrorFFunction(const char *f, va_list args) +{ + if (OsVendorVErrorFFatal == 0) + { + char buffer[1024]; + + vsnprintf(buffer, sizeof(buffer), f, args); + + nxagentStartRedirectToClientsLog(); + + fprintf(stderr, buffer); + + nxagentEndRedirectToClientsLog(); + } + else + { + LogVWrite(-1, f, args); + } +} + +void OsVendorStartRedirectErrorFFunction() +{ + nxagentStartRedirectToClientsLog(); +} + +void OsVendorEndRedirectErrorFFunction() +{ + nxagentEndRedirectToClientsLog(); +} + +/* this is just to get the server to link on AIX */ +#ifdef AIXV3 +int SelectWaitTime = 10000; /* usec */ +#endif + +#ifdef DPMSExtension + +void DPMSSet(int level) +{ +} + +int DPMSGet(int *level) +{ + return -1; +} + +Bool DPMSSupported(void) +{ + return 1; +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Init.h b/nx-X11/programs/Xserver/hw/nxagent/Init.h new file mode 100644 index 000000000..63e27bada --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Init.h @@ -0,0 +1,40 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Init_H__ +#define __Init_H__ + +extern int nxagentDoFullGeneration; + +extern int nxagentBackingStore; +extern int nxagentSaveUnder; + +#endif /* __Init_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c new file mode 100644 index 000000000..dbdfc5b19 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c @@ -0,0 +1,1359 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ +#include +#include +#include +#include +#include + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "keysym.h" +#include "screenint.h" +#include "inputstr.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "dixstruct.h" +#include "extnsionst.h" + +#include "Agent.h" +#include "Display.h" +#include "Screen.h" +#include "Keyboard.h" +#include "Events.h" +#include "Options.h" + +#include "NXlib.h" + +#ifdef XKB + +#include +#include +#include + +#endif /* XKB */ + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef WATCH + +#ifdef WATCH +#include "unistd.h" +#endif + +/* + * Unfortunately we cannot just include XKBlib.h. + * It conflicts with the server side definitions + * of the same symbols. This is more a X problem + * than our. + */ + +#ifdef XKB + +extern Bool XkbQueryExtension( +#if NeedFunctionPrototypes + Display * /* dpy */, + int * /* opcodeReturn */, + int * /* eventBaseReturn */, + int * /* errorBaseReturn */, + int * /* majorRtrn */, + int * /* minorRtrn */ +#endif +); + +extern XkbDescPtr XkbGetKeyboard( +#if NeedFunctionPrototypes + Display * /* dpy */, + unsigned int /* which */, + unsigned int /* deviceSpec */ +#endif +); + +extern Status XkbGetControls( +#if NeedFunctionPrototypes + Display * /* dpy */, + unsigned long /* which */, + XkbDescPtr /* desc */ +#endif +); + +#ifndef XKB_BASE_DIRECTORY +#define XKB_BASE_DIRECTORY "/usr/share/X11/xkb" +#endif +#ifndef XKB_ALTERNATE_BASE_DIRECTORY +#define XKB_ALTERNATE_BASE_DIRECTORY "/usr/X11R6/lib/X11/xkb" +#endif +#ifndef XKB_CONFIG_FILE +#define XKB_CONFIG_FILE "X0-config.keyboard" +#endif +#ifndef XKB_DFLT_RULES_FILE +#define XKB_DFLT_RULES_FILE "xfree86" +#endif +#ifndef XKB_ALTS_RULES_FILE +#define XKB_ALTS_RULES_FILE "xorg" +#endif +#ifndef XKB_DFLT_KB_LAYOUT +#define XKB_DFLT_KB_LAYOUT "us" +#endif +#ifndef XKB_DFLT_KB_MODEL +#define XKB_DFLT_KB_MODEL "pc102" +#endif +#ifndef XKB_DFLT_KB_VARIANT +#define XKB_DFLT_KB_VARIANT NULL +#endif +#ifndef XKB_DFLT_KB_OPTIONS +#define XKB_DFLT_KB_OPTIONS NULL +#endif + +#define NXAGENT_KEYMAP_DIR_FILE "keymap.dir" + +extern int XkbDfltRepeatDelay; +extern int XkbDfltRepeatInterval; + +#endif /* XKB */ + +/* + * Save the values queried from X server. + */ + +XkbAgentInfoRec nxagentXkbInfo = { -1, -1, -1, -1, -1 }; + +/* + * Keyboard status, updated through XKB + * events. + */ + +XkbAgentStateRec nxagentXkbState = { 0, 0, 0, 0, 0 }; + +/* + * Info for disabling/enabling Xkb extension. + */ + +XkbWrapperRec nxagentXkbWrapper; + +extern char *nxagentKeyboard; + +static char *nxagentXkbGetRules(void); + +unsigned int nxagentAltMetaMask; + +void nxagentCheckAltMetaKeys(CARD8, int); + +static int nxagentSaveKeyboardDeviceData(DeviceIntPtr dev, DeviceIntPtr devBackup); + +static int nxagentRestoreKeyboardDeviceData(DeviceIntPtr devBackup, DeviceIntPtr dev); + +static int nxagentFreeKeyboardDeviceData(DeviceIntPtr dev); + +static void nxagentCheckXkbBaseDirectory(void) +{ + + /* + * Set XkbBaseDirectory global + * variable appropriately. + */ + + #ifdef TEST + fprintf(stderr, "nxagentCheckXkbBaseDirectory: " + "Before calling _NXGetXkbBasePath.\n"); + + fprintf(stderr, "nxagentCheckXkbBaseDirectory: " + "XkbBaseDirectory varible [%s].\n", + XkbBaseDirectory); + #endif + + XkbBaseDirectory = _NXGetXkbBasePath(XkbBaseDirectory); + + #ifdef TEST + fprintf(stderr, "nxagentCheckXkbBaseDirectory: " + "After calling _NXGetXkbBasePath.\n"); + + fprintf(stderr, "nxagentCheckXkbBaseDirectory: " + "XkbBaseDirectory varible [%s].\n", + XkbBaseDirectory); + #endif + + return; +} + +static char *nxagentXkbGetRules() +{ + int ret; + int size, sizeDflt, sizeAlt; + char *path; + struct stat buf; + + #ifdef TEST + fprintf(stderr, "nxagentXkbGetRules: XkbBaseDirectory [%s].\n", + XkbBaseDirectory); + #endif + + sizeDflt = strlen(XKB_DFLT_RULES_FILE); + sizeAlt = strlen(XKB_ALTS_RULES_FILE); + size = strlen(XkbBaseDirectory) + strlen("/rules/"); + size += (sizeDflt > sizeAlt) ? sizeDflt: sizeAlt; + + if ((path = malloc((size + 1) * sizeof(char))) == NULL) + { + FatalError("nxagentXkbGetRules: malloc failed."); + } + + strcpy(path, XkbBaseDirectory); + strcat(path, "/rules/"); + strcat(path, XKB_DFLT_RULES_FILE); + ret = stat(path, &buf); + + if (ret == 0) + { + free(path); + return XKB_DFLT_RULES_FILE; + } + + #ifdef TEST + fprintf(stderr, "nxagentXkbGetRules: WARNING! Failed to stat file [%s]: %s.\n", path, strerror(ret)); + #endif + + strcpy(path, XkbBaseDirectory); + strcat(path, "/rules/"); + strcat(path, XKB_ALTS_RULES_FILE); + ret = stat(path, &buf); + + if (ret == 0) + { + free(path); + return XKB_ALTS_RULES_FILE; + } + + #ifdef WARNING + fprintf(stderr, "nxagentXkbGetRules: WARNING! Failed to stat file [%s]: %s.\n", path, strerror(ret)); + #endif + + free(path); + return XKB_DFLT_RULES_FILE; +} + +void nxagentBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls) +{ + XBell(nxagentDisplay, volume); +} + +void nxagentChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) +{ + #ifdef XKB + + XkbSrvInfoPtr xkbi; + XkbControlsPtr xkbc; + + if (!noXkbExtension) + { + xkbi = pDev -> key -> xkbInfo; + xkbc = xkbi -> desc -> ctrls; + + /* + * We want to prevent agent generating auto-repeated + * keystrokes. Let's intercept any attempt by appli- + * cations to change the default timeouts on the + * nxagent device. + */ + + #ifdef TEST + fprintf(stderr, "nxagentChangeKeyboardControl: Repeat delay was [%d] interval was [%d].\n", + xkbc -> repeat_delay, xkbc -> repeat_interval); + #endif + + xkbc -> repeat_delay = ~ 0; + xkbc -> repeat_interval = ~ 0; + + #ifdef TEST + fprintf(stderr, "nxagentChangeKeyboardControl: Repeat delay is now [%d] interval is now [%d].\n", + xkbc -> repeat_delay, xkbc -> repeat_interval); + #endif + } + + #endif + + /* + * If enabled, propagate the changes to the + * devices attached to the real X server. + */ + + if (nxagentOption(DeviceControl) == True) + { + unsigned long value_mask; + XKeyboardControl values; + int i; + + #ifdef TEST + fprintf(stderr, "nxagentChangeKeyboardControl: WARNING! Propagating changes to keyboard settings.\n"); + #endif + + value_mask = KBKeyClickPercent | + KBBellPercent | + KBBellPitch | + KBBellDuration; + + values.key_click_percent = ctrl->click; + values.bell_percent = ctrl->bell; + values.bell_pitch = ctrl->bell_pitch; + values.bell_duration = ctrl->bell_duration; + + /* + * Don't propagate the auto repeat mode. It is forced to be + * off in the agent server. + * + * value_mask |= KBAutoRepeatMode; + * values.auto_repeat_mode = ctrl->autoRepeat ? + * AutoRepeatModeOn : AutoRepeatModeOff; + */ + + XChangeKeyboardControl(nxagentDisplay, value_mask, &values); + + /* + * At this point, we need to walk through the vector and + * compare it to the current server vector. If there are + * differences, report them. + */ + + value_mask = KBLed | KBLedMode; + + for (i = 1; i <= 32; i++) + { + values.led = i; + values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff; + + XChangeKeyboardControl(nxagentDisplay, value_mask, &values); + } + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentChangeKeyboardControl: WARNING! Not propagating changes to keyboard settings.\n"); + #endif +} + +int nxagentKeyboardProc(DeviceIntPtr pDev, int onoff) +{ + XModifierKeymap *modifier_keymap; + KeySym *keymap; + int mapWidth; + int min_keycode, max_keycode; + KeySymsRec keySyms; + CARD8 modmap[256]; + int i, j; + XKeyboardState values; + char *model = NULL, *layout = NULL; + int free_model = 0, free_layout = 0; + XkbDescPtr xkb = NULL; + + int ret; + + switch (onoff) + { + case DEVICE_INIT: + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_INIT].\n"); + #endif + + if (NXDisplayError(nxagentDisplay) == 1) + { + return Success; + } + + #ifdef WATCH + + fprintf(stderr, "nxagentKeyboardProc: Watchpoint 9.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +N/A +*/ + + sleep(30); + + #endif + + /* + * Prevent agent from generating auto-repeat keystroke. + * Note that this is working only if XKB is enabled. + * A better solution should account cases where XKB is + * not available. Check also the behaviour of the + * DeviceControl nxagent option. + */ + + XkbDfltRepeatDelay = ~ 0; + XkbDfltRepeatInterval = ~ 0; + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Set repeat delay to [%u] interval to [%u].\n", + XkbDfltRepeatDelay, XkbDfltRepeatInterval); + #endif + + modifier_keymap = XGetModifierMapping(nxagentDisplay); + + if (modifier_keymap == NULL) + { + return -1; + } + + XDisplayKeycodes(nxagentDisplay, &min_keycode, &max_keycode); +#ifdef _XSERVER64 + { + KeySym64 *keymap64; + int i, len; + keymap64 = XGetKeyboardMapping(nxagentDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); + + if (keymap == NULL) + { + XFreeModifiermap(modifier_keymap); + + return -1; + } + + len = (max_keycode - min_keycode + 1) * mapWidth; + keymap = (KeySym *)xalloc(len * sizeof(KeySym)); + for(i = 0; i < len; ++i) + keymap[i] = keymap64[i]; + XFree(keymap64); + } + +#else /* #ifdef _XSERVER64 */ + + keymap = XGetKeyboardMapping(nxagentDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); + + if (keymap == NULL) + { + XFreeModifiermap(modifier_keymap); + + return -1; + } + +#endif /* #ifdef _XSERVER64 */ + + nxagentAltMetaMask = 0; + + for (i = 0; i < 256; i++) + modmap[i] = 0; + for (j = 0; j < 8; j++) + for(i = 0; i < modifier_keymap->max_keypermod; i++) { + CARD8 keycode; + if ((keycode = + modifier_keymap-> + modifiermap[j * modifier_keymap->max_keypermod + i])) + modmap[keycode] |= 1< 0) + { + nxagentCheckAltMetaKeys(keycode, j); + } + } + XFreeModifiermap(modifier_keymap); + + keySyms.minKeyCode = min_keycode; + keySyms.maxKeyCode = max_keycode; + keySyms.mapWidth = mapWidth; + keySyms.map = keymap; + +#ifdef XKB + + /* + * First of all the validity + * of XkbBaseDirectory global + * variable is checked. + */ + + nxagentCheckXkbBaseDirectory(); + + if (noXkbExtension) { + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: No XKB extension.\n"); + #endif + +XkbError: + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: XKB error.\n"); + #endif + + XkbFreeKeyboard(xkb, XkbAllComponentsMask, True); + xkb = NULL; + if (free_model) + { + free_model = 0; + free(model); + } + if (free_layout) + { + free_layout = 0; + free(layout); + } +#endif + XGetKeyboardControl(nxagentDisplay, &values); + + memmove((char *) defaultKeyboardControl.autoRepeats, + (char *) values.auto_repeats, sizeof(values.auto_repeats)); + + ret = InitKeyboardDeviceStruct((DevicePtr) pDev, &keySyms, modmap, + nxagentBell, nxagentChangeKeyboardControl); + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: InitKeyboardDeviceStruct returns [%d].\n", ret); + #endif + +#ifdef XKB + } else { + FILE *file; + XkbConfigRtrnRec config; + + int nxagentXkbConfigFilePathSize; + + char *nxagentXkbConfigFilePath; + + XkbComponentNamesRec names; + char *rules, *variants, *options; + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Using XKB extension.\n"); + #endif + + memset(&names, 0, sizeof(XkbComponentNamesRec)); + + rules = nxagentXkbGetRules(); + + if ((nxagentKeyboard != NULL) && (strcmp(nxagentKeyboard, "query") !=0)) + { + for (i = 0; nxagentKeyboard[i] != '/' && nxagentKeyboard[i] != 0; i++); + + if(nxagentKeyboard[i] == 0 || nxagentKeyboard[i + 1] == 0 || i == 0) + { + ErrorF("Warning: Wrong keyboard type: %s.\n",nxagentKeyboard); + + goto XkbError; + } + + free_model = 1; + model = malloc(i + 1); + + strncpy(model, nxagentKeyboard, i); + + model[i] = '\0'; + + free_layout = 1; + layout = malloc(strlen(&nxagentKeyboard[i + 1]) + 1); + + strcpy(layout, &nxagentKeyboard[i + 1]); + + /* + * There is no description for pc105 on Solaris. + * Need to revert to the closest approximation. + */ + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Using keyboard model [%s] with layout [%s].\n", + model, layout); + #endif + + #ifdef __sun + + if (strcmp(model, "pc105") == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: WARNING! Keyboard model 'pc105' unsupported on Solaris.\n"); + + fprintf(stderr, "nxagentKeyboardProc: WARNING! Forcing keyboard model to 'pc104'.\n"); + #endif + + strcpy(model, "pc104"); + } + + #endif + } + else + { + layout = XKB_DFLT_KB_LAYOUT; + model = XKB_DFLT_KB_MODEL; + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Using default keyboard: model [%s] layout [%s].\n", + model, layout); + #endif + } + + variants = XKB_DFLT_KB_VARIANT; + options = XKB_DFLT_KB_OPTIONS; + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: XkbInitialMap [%s]\n", XkbInitialMap ? XkbInitialMap: "NULL"); + #endif + + if (XkbInitialMap) { + if ((names.keymap = strchr(XkbInitialMap, '/')) != NULL) + ++names.keymap; + else + names.keymap = XkbInitialMap; + } + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Init XKB extension.\n"); + #endif + + if (XkbQueryExtension(nxagentDisplay, + &nxagentXkbInfo.Opcode, + &nxagentXkbInfo.EventBase, + &nxagentXkbInfo.ErrorBase, + &nxagentXkbInfo.MajorVersion, + &nxagentXkbInfo.MinorVersion) == 0) + { + ErrorF("Unable to initialize XKEYBOARD extension.\n"); + + goto XkbError; + } + + xkb = XkbGetKeyboard(nxagentDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd); + + if (xkb == NULL || xkb->geom == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: No current keyboard.\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: No keyboard, going to set rules and init device.\n"); + #endif + + XkbSetRulesDflts(rules, model, layout, variants, options); + XkbInitKeyboardDeviceStruct((pointer)pDev, &names, &keySyms, modmap, + nxagentBell, nxagentChangeKeyboardControl); + + if (!nxagentKeyboard || + (nxagentKeyboard && (strcmp(nxagentKeyboard, "query") == 0))) + { + goto XkbError; + } + + goto XkbEnd; + } + + XkbGetControls(nxagentDisplay, XkbAllControlsMask, xkb); + + nxagentXkbConfigFilePathSize = strlen(XkbBaseDirectory) + + strlen(XKB_CONFIG_FILE) + 1; + + nxagentXkbConfigFilePath = malloc((nxagentXkbConfigFilePathSize + 1) * sizeof(char)); + + if ( nxagentXkbConfigFilePath == NULL) + { + FatalError("nxagentKeyboardProc: malloc failed."); + } + + strcpy(nxagentXkbConfigFilePath, XkbBaseDirectory); + strcat(nxagentXkbConfigFilePath, "/"); + strcat(nxagentXkbConfigFilePath, XKB_CONFIG_FILE); + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: nxagentXkbConfigFilePath [%s].\n", + nxagentXkbConfigFilePath); + #endif + + if ((file = fopen(nxagentXkbConfigFilePath, "r")) != NULL) { + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Going to parse config file.\n"); + #endif + + if (XkbCFParse(file, XkbCFDflts, xkb, &config) == 0) { + ErrorF("Error parsing config file.\n"); + + free(nxagentXkbConfigFilePath); + + fclose(file); + goto XkbError; + } + if (config.rules_file) + rules = config.rules_file; + if (config.model) + { + if (free_model) + { + free_model = 0; + free(model); + } + model = config.model; + } + if (config.layout) + { + if (free_layout) + { + free_layout = 0; + free(layout); + } + layout = config.layout; + } + if (config.variant) + variants = config.variant; + if (config.options) + options = config.options; + + free(nxagentXkbConfigFilePath); + + fclose(file); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: No config file.\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: No config file, going to set rules and init device.\n"); + #endif + + XkbSetRulesDflts(rules, model, layout, variants, options); + XkbInitKeyboardDeviceStruct((pointer)pDev, &names, &keySyms, modmap, + nxagentBell, nxagentChangeKeyboardControl); + + if (!nxagentKeyboard || + (nxagentKeyboard && (strcmp(nxagentKeyboard, "query") == 0))) + { + goto XkbError; + } + + goto XkbEnd; + } + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Going to set rules and init device.\n"); + #endif + + XkbSetRulesDflts(rules, model, layout, variants, options); + XkbInitKeyboardDeviceStruct((pointer)pDev, &names, &keySyms, modmap, + nxagentBell, nxagentChangeKeyboardControl); + XkbDDXChangeControls((pointer)pDev, xkb->ctrls, xkb->ctrls); + +XkbEnd: + if (free_model) + { + free_model = 0; + free(model); + } + + if (free_layout) + { + free_layout = 0; + free(layout); + } + + XkbFreeKeyboard(xkb, XkbAllComponentsMask, True); + + xkb = NULL; + } +#endif + + #ifdef WATCH + + fprintf(stderr, "nxagentKeyboardProc: Watchpoint 10.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#1 U 3 2 80320 bits (10 KB) -> 28621 bits (3 KB) -> 26773/1 -> 9540/1 = 2.806:1 +#98 1 256 bits (0 KB) -> 27 bits (0 KB) -> 256/1 -> 27/1 = 9.481:1 +#101 1 32000 bits (4 KB) -> 2940 bits (0 KB) -> 32000/1 -> 2940/1 = 10.884:1 +#119 1 384 bits (0 KB) -> 126 bits (0 KB) -> 384/1 -> 126/1 = 3.048:1 +*/ + + sleep(30); + + #endif + +#ifdef _XSERVER64 + xfree(keymap); +#else + XFree(keymap); +#endif + break; + case DEVICE_ON: + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_ON].\n"); + #endif + + if (NXDisplayError(nxagentDisplay) == 1) + { + return Success; + } + + #ifdef WATCH + + fprintf(stderr, "nxagentKeyboardProc: Watchpoint 11.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#117 1 320 bits (0 KB) -> 52 bits (0 KB) -> 320/1 -> 52/1 = 6.154:1 +*/ + + sleep(30); + + #endif + + nxagentEnableKeyboardEvents(); + + break; + + case DEVICE_OFF: + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_OFF].\n"); + #endif + + if (NXDisplayError(nxagentDisplay) == 1) + { + return Success; + } + + nxagentDisableKeyboardEvents(); + + break; + + case DEVICE_CLOSE: + + #ifdef TEST + fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_CLOSE].\n"); + #endif + + break; + } + + return Success; +} + +Bool LegalModifier(key, pDev) + unsigned int key; + DevicePtr pDev; +{ + return TRUE; +} + +void nxagentNotifyKeyboardChanges(int oldMinKeycode, int oldMaxKeycode) +{ + #ifdef XKB + + if (!noXkbExtension) + { + DeviceIntPtr dev; + XkbDescPtr xkb; + xkbNewKeyboardNotify nkn; + + dev = inputInfo.keyboard; + xkb = dev -> key -> xkbInfo -> desc; + + nkn.deviceID = nkn.oldDeviceID = dev -> id; + nkn.minKeyCode = 8; + nkn.maxKeyCode = 255; + nkn.oldMinKeyCode = oldMinKeycode; + nkn.oldMaxKeyCode = oldMaxKeycode; + nkn.requestMajor = XkbReqCode; + nkn.requestMinor = X_kbGetKbdByName; + nkn.changed = XkbNKN_KeycodesMask; + + XkbSendNewKeyboardNotify(dev, &nkn); + } + else + { + + #endif + + int i; + xEvent event; + + event.u.u.type = MappingNotify; + event.u.mappingNotify.request = MappingKeyboard; + event.u.mappingNotify.firstKeyCode = inputInfo.keyboard -> key -> curKeySyms.minKeyCode; + event.u.mappingNotify.count = inputInfo.keyboard -> key -> curKeySyms.maxKeyCode - + inputInfo.keyboard -> key -> curKeySyms.minKeyCode; + + /* + * 0 is the server client + */ + + for (i = 1; i < currentMaxClients; i++) + { + if (clients[i] && clients[i] -> clientState == ClientStateRunning) + { + event.u.u.sequenceNumber = clients[i] -> sequence; + WriteEventsToClient(clients[i], 1, &event); + } + } + + #ifdef XKB + + } + + #endif + +} + +int nxagentResetKeyboard(void) +{ + DeviceIntPtr dev = inputInfo.keyboard; + DeviceIntPtr devBackup; + + int result; + int oldMinKeycode = 8; + int oldMaxKeycode = 255; + + int savedBellPercent; + int savedBellPitch; + int savedBellDuration; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return 0; + } + + /* + * Save bell settings. + */ + + savedBellPercent = inputInfo.keyboard -> kbdfeed -> ctrl.bell; + savedBellPitch = inputInfo.keyboard -> kbdfeed -> ctrl.bell_pitch; + savedBellDuration = inputInfo.keyboard -> kbdfeed -> ctrl.bell_duration; + + #ifdef TEST + fprintf(stderr, "nxagentResetKeyboard: bellPercent [%d] bellPitch [%d] bellDuration [%d].\n", + savedBellPercent, savedBellPitch, savedBellDuration); + #endif + + devBackup = xalloc(sizeof(DeviceIntRec)); + + if (devBackup == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentSaveKeyboardDeviceData: PANIC! Can't allocate backup structure.\n"); + #endif + } + else + { + memset(devBackup, 0, sizeof(DeviceIntRec)); + } + + nxagentSaveKeyboardDeviceData(dev, devBackup); + + if (dev->key) + { + #ifdef XKB + if (noXkbExtension == 0 && dev->key->xkbInfo) + { + oldMinKeycode = dev->key->xkbInfo -> desc -> min_key_code; + oldMaxKeycode = dev->key->xkbInfo -> desc -> max_key_code; + } + #endif + + dev->key=NULL; + } + + dev->focus=NULL; + + dev->kbdfeed=NULL; + + #ifdef XKB + nxagentTuneXkbWrapper(); + #endif + + result = (*inputInfo.keyboard -> deviceProc)(inputInfo.keyboard, DEVICE_INIT); + + if (result == Success && inputInfo.keyboard -> key != NULL) + { + + /* + * Restore bell settings. + */ + + inputInfo.keyboard -> kbdfeed -> ctrl.bell = savedBellPercent; + inputInfo.keyboard -> kbdfeed -> ctrl.bell_pitch = savedBellPitch; + inputInfo.keyboard -> kbdfeed -> ctrl.bell_duration = savedBellDuration; + + nxagentNotifyKeyboardChanges(oldMinKeycode, oldMaxKeycode); + + nxagentFreeKeyboardDeviceData(devBackup); + + free(devBackup); + + return 1; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentResetKeyboard: Can't initialize the keyboard device.\n"); + #endif + + nxagentRestoreKeyboardDeviceData(devBackup, dev); + + return 0; + } +} + +void nxagentCheckAltMetaKeys(CARD8 keycode, int j) +{ + if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Meta_L)) + { + nxagentAltMetaMask |= 1 << j; + } + + if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Meta_R)) + { + nxagentAltMetaMask |= 1 << j; + } + + if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Alt_L)) + { + nxagentAltMetaMask |= 1 << j; + } + + if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Alt_R)) + { + nxagentAltMetaMask |= 1 << j; + } +} + +static int nxagentSaveKeyboardDeviceData(DeviceIntPtr dev, DeviceIntPtr devBackup) +{ + if (devBackup == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentSaveKeyboardDeviceData: PANIC! Pointer to backup structure is null.\n"); + #endif + + return -1; + } + + devBackup -> key = dev -> key; + + devBackup -> focus = dev -> focus; + + devBackup -> kbdfeed = dev -> kbdfeed; + + #ifdef DEBUG + fprintf(stderr, "nxagentSaveKeyboardDeviceData: Saved device data.\n"); + #endif + + return 1; +} + +static int nxagentRestoreKeyboardDeviceData(DeviceIntPtr devBackup, DeviceIntPtr dev) +{ + if (devBackup == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentRestoreKeyboardDeviceData: PANIC! Pointer to backup structure is null.\n"); + #endif + + return -1; + } + + dev -> key = devBackup -> key; + + dev -> focus = devBackup -> focus; + + dev -> kbdfeed = devBackup -> kbdfeed; + + #ifdef DEBUG + fprintf(stderr, "nxagentRestoreKeyboardDeviceData: Restored device data.\n"); + #endif + + return 1; +} + + +static int nxagentFreeKeyboardDeviceData(DeviceIntPtr dev) +{ + KbdFeedbackPtr k, knext; + + if (dev == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentFreeKeyboardDeviceData: PANIC! Pointer to device structure is null.\n"); + #endif + + return -1; + } + + if (dev->key) + { + #ifdef XKB + if (noXkbExtension == 0 && dev->key->xkbInfo) + { + XkbFreeInfo(dev->key->xkbInfo); + dev->key->xkbInfo = NULL; + } + #endif + + xfree(dev->key->curKeySyms.map); + xfree(dev->key->modifierKeyMap); + xfree(dev->key); + + dev->key=NULL; + } + + if (dev->focus) + { + xfree(dev->focus->trace); + xfree(dev->focus); + dev->focus=NULL; + } + + for (k = dev->kbdfeed; k; k = knext) + { + knext = k->next; + #ifdef XKB + if (k->xkb_sli) + XkbFreeSrvLedInfo(k->xkb_sli); + #endif + xfree(k); + } + + #ifdef DEBUG + fprintf(stderr, "nxagentFreeKeyboardDeviceData: Freed device data.\n"); + #endif + + return 1; +} + +#if XKB + +int ProcXkbInhibited(register ClientPtr client) +{ + unsigned char majorop; + unsigned char minorop; + + #ifdef TEST + fprintf(stderr, "ProcXkbInhibited: Called.\n"); + #endif + + majorop = ((xReq *)client->requestBuffer)->reqType; + + #ifdef PANIC + if (majorop != (unsigned char)nxagentXkbWrapper.base) + { + fprintf(stderr, "ProcXkbInhibited: MAJOROP is [%d] but should be [%d].\n", + majorop, nxagentXkbWrapper.base); + } + #endif + + minorop = *((unsigned char *) client->requestBuffer + 1); + + #ifdef TEST + fprintf(stderr, "ProcXkbInhibited: MAJOROP is [%d] MINOROP is [%d].\n", + majorop, minorop); + #endif + + switch (minorop) + { + case X_kbLatchLockState: + case X_kbSetControls: + case X_kbSetCompatMap: + case X_kbSetIndicatorMap: + case X_kbSetNamedIndicator: + case X_kbSetNames: + case X_kbSetGeometry: + case X_kbSetDebuggingFlags: + case X_kbSetMap: + { + return client->noClientException; + } + case X_kbGetKbdByName: + { + return BadAccess; + } + default: + { + return (client->swapped ? nxagentXkbWrapper.SProcXkbDispatchBackup(client) : + nxagentXkbWrapper.ProcXkbDispatchBackup(client)); + } + } +} + +void nxagentInitXkbWrapper(void) +{ + ExtensionEntry * extension; + + #ifdef TEST + fprintf(stderr, "nxagentInitXkbWrapper: Called.\n"); + #endif + + if (nxagentOption(InhibitXkb) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentInitXkbWrapper: Nothing to do.\n"); + #endif + + return; + } + + memset(&nxagentXkbWrapper, 0, sizeof(XkbWrapperRec)); + + extension = CheckExtension("XKEYBOARD"); + + if (extension != NULL) + { + nxagentXkbWrapper.base = extension -> base; + nxagentXkbWrapper.eventBase = extension -> eventBase; + nxagentXkbWrapper.errorBase = extension -> errorBase; + nxagentXkbWrapper.ProcXkbDispatchBackup = NULL; + nxagentXkbWrapper.SProcXkbDispatchBackup = NULL; + + #ifdef TEST + fprintf(stderr, "nxagentInitXkbWrapper: base [%d] eventBase [%d] errorBase [%d].\n", + extension -> base, extension -> eventBase, extension -> errorBase); + #endif + } + else + { + nxagentXkbWrapper.base = -1; + + #ifdef TEST + fprintf(stderr, "nxagentInitXkbWrapper: XKEYBOARD extension not found.\n"); + #endif + } +} + +void nxagentDisableXkbExtension(void) +{ + #ifdef TEST + fprintf(stderr, "nxagentDisableXkbExtension: Called.\n"); + #endif + + if (nxagentXkbWrapper.base > 0) + { + if (nxagentXkbWrapper.ProcXkbDispatchBackup == NULL) + { + nxagentXkbWrapper.ProcXkbDispatchBackup = ProcVector[nxagentXkbWrapper.base]; + + ProcVector[nxagentXkbWrapper.base] = ProcXkbInhibited; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentDisableXkbExtension: Nothing to be done for ProcXkbDispatch.\n"); + } + #endif + + if (nxagentXkbWrapper.SProcXkbDispatchBackup == NULL) + { + nxagentXkbWrapper.SProcXkbDispatchBackup = SwappedProcVector[nxagentXkbWrapper.base]; + + SwappedProcVector[nxagentXkbWrapper.base] = ProcXkbInhibited; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentDisableXkbExtension: Nothing to be done for SProcXkbDispatch.\n"); + } + #endif + } +} + +void nxagentEnableXkbExtension(void) +{ + #ifdef TEST + fprintf(stderr, "nxagentEnableXkbExtension: Called.\n"); + #endif + + if (nxagentXkbWrapper.base > 0) + { + if (nxagentXkbWrapper.ProcXkbDispatchBackup != NULL) + { + ProcVector[nxagentXkbWrapper.base] = nxagentXkbWrapper.ProcXkbDispatchBackup; + + nxagentXkbWrapper.ProcXkbDispatchBackup = NULL; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentEnableXkbExtension: Nothing to be done for ProcXkbDispatch.\n"); + } + #endif + + if (nxagentXkbWrapper.SProcXkbDispatchBackup != NULL) + { + SwappedProcVector[nxagentXkbWrapper.base] = nxagentXkbWrapper.SProcXkbDispatchBackup; + + nxagentXkbWrapper.SProcXkbDispatchBackup = NULL; + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentEnableXkbExtension: Nothing to be done for SProcXkbDispatch.\n"); + } + #endif + } +} + +void nxagentTuneXkbWrapper(void) +{ + if (nxagentOption(InhibitXkb) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentTuneXkbWrapper: Nothing to do.\n"); + #endif + + return; + } + + if (nxagentKeyboard != NULL && + strcmp(nxagentKeyboard, "query") == 0) + { + nxagentDisableXkbExtension(); + } + else + { + nxagentEnableXkbExtension(); + } +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keyboard.h b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.h new file mode 100644 index 000000000..f292402d2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.h @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Keyboard_H__ +#define __Keyboard_H__ + +#define NXAGENT_KEYBOARD_EVENT_MASK \ + (KeyPressMask | KeyReleaseMask | FocusChangeMask | KeymapStateMask) + +#define NXAGENT_KEYBOARD_EXTENSION_EVENT_MASK \ + (XkbStateNotifyMask) + +/* + * Queried at XKB initialization. + */ + +typedef struct _XkbAgentInfo +{ + int Opcode; + int EventBase; + int ErrorBase; + int MajorVersion; + int MinorVersion; + +} XkbAgentInfoRec; + +extern XkbAgentInfoRec nxagentXkbInfo; + +typedef struct _XkbAgentState +{ + int Locked; + int Caps; + int Num; + int Focus; + int Initialized; + +} XkbAgentStateRec; + +extern XkbAgentStateRec nxagentXkbState; + +/* + * Info for enabling/disabling Xkb. + */ + +typedef struct _XkbWrapper +{ + int base; + int eventBase; + int errorBase; + int (* ProcXkbDispatchBackup)(ClientPtr); + int (* SProcXkbDispatchBackup)(ClientPtr); + +} XkbWrapperRec; + +extern XkbWrapperRec nxagentXkbWrapper; + +extern char *nxagentKeyboard; + +/* + * Keyboard device procedure + * and utility functions. + */ + +void nxagentBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls); + +int nxagentKeyboardProc(DeviceIntPtr pDev, int onoff); + +void nxagentChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl); + +void nxagentNotifyKeyboardChanges(int oldMinKeycode, int oldMaxKeycode); + +int nxagentResetKeyboard(void); + +#ifdef XKB + +void nxagentInitXkbWrapper(void); + +void nxagentDisableXkbExtension(void); + +void nxagentEnableXkbExtension(void); + +void nxagentTuneXkbWrapper(void); + +#endif + +#endif /* __Keyboard_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c new file mode 100644 index 000000000..ea06913f8 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "X.h" +#include "keysym.h" + +#include "screenint.h" +#include "scrnintstr.h" + +#include "Agent.h" +#include "Display.h" +#include "Events.h" +#include "Options.h" +#include "Keystroke.h" +#include "Drawable.h" + +extern Bool nxagentWMIsRunning; +extern Bool nxagentIpaq; + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +int nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result) +{ + KeySym sym; + int index = 0; + + *result = doNothing; + + /* + * I don't know how much hard work is doing this operation. + * Do we need a cache ? + */ + + sym = XKeycodeToKeysym(nxagentDisplay, X -> keycode, index); + + if (sym == XK_VoidSymbol || sym == NoSymbol) + { + return 0; + } + + #ifdef TEST + fprintf(stderr, "nxagentCheckSpecialKeystroke: got code %x - state %x - sym %lx\n", + X -> keycode, X -> state, sym); + #endif + + /* + * Check special keys. + */ + + /* + * FIXME: We should use the keysym instead that the keycode + * here. + */ + + if (X -> keycode == 130 && nxagentIpaq) + { + *result = doStartKbd; + + return 1; + } + + if ((X -> state & nxagentAltMetaMask) && + ((X -> state & (ControlMask | ShiftMask)) == ControlMask)) + { + switch (sym) + { + case XK_t: + case XK_T: + { + *result = doCloseSession; + + break; + } + case XK_f: + case XK_F: + { + if (nxagentOption(Rootless) == False) + { + *result = doSwitchFullscreen; + } + + break; + } + case XK_m: + case XK_M: + { + if (nxagentOption(Rootless) == False) + { + *result = doMinimize; + } + + break; + } + case XK_Left: + case XK_KP_Left: + { + if (nxagentOption(Rootless) == False && + nxagentOption(DesktopResize) == False) + { + *result = doViewportLeft; + } + + break; + } + case XK_Up: + case XK_KP_Up: + { + if (nxagentOption(Rootless) == False && + nxagentOption(DesktopResize) == False) + { + *result = doViewportUp; + } + + break; + } + case XK_Right: + case XK_KP_Right: + { + if (nxagentOption(Rootless) == False && + nxagentOption(DesktopResize) == False) + { + *result = doViewportRight; + } + + break; + } + case XK_Down: + case XK_KP_Down: + { + if (nxagentOption(Rootless) == 0 && + nxagentOption(DesktopResize) == 0) + { + *result = doViewportDown; + } + + break; + } + case XK_R: + case XK_r: + { + if (nxagentOption(Rootless) == 0) + { + *result = doSwitchResizeMode; + } + + break; + } + case XK_E: + case XK_e: + { + *result = doSwitchDeferMode; + + break; + } + case XK_BackSpace: + case XK_Terminate_Server: + { + /* + * Discard Ctrl-Alt-BackSpace key. + */ + + return 1; + + break; + } + + case XK_J: + case XK_j: + { + nxagentForceSynchronization = 1; + + return 1; + } + + #ifdef DUMP + + case XK_A: + case XK_a: + { + /* + * Used to test the lazy encoding. + */ + + nxagentRegionsOnScreen(); + + return 1; + } + + #endif + } + } + + return (*result == doNothing) ? 0 : 1; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h new file mode 100644 index 000000000..49a35db1d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Keystroke_H__ +#define __Keystroke_H__ + +#include "Events.h" + +extern int nxagentCheckSpecialKeystroke(XKeyEvent*, enum HandleEventResult*); + +unsigned int nxagentAltMetaMask; + +#endif /* __Keystroke_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/LICENSE b/nx-X11/programs/Xserver/hw/nxagent/LICENSE new file mode 100644 index 000000000..f3e15ee70 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/LICENSE @@ -0,0 +1,26 @@ +Copyright (C) 2001, 2007 NoMachine - http://www.nomachine.com/. + +NXAGENT and NX extensions to X are copyright of NoMachine. + +Redistribution and use of this software is allowed according to the +following terms: + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License Version 2, and +not any other version, as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTA- +BILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, you can request a copy to NoMachine +or write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +Parts of this software are derived from XFree86 and X.org projects. +Other copyrights and the MIT/X11 license applies to different sources. +Please check the applicable copyrights in each file or subdirectory. + +All rights reserved. diff --git a/nx-X11/programs/Xserver/hw/nxagent/Literals.h b/nx-X11/programs/Xserver/hw/nxagent/Literals.h new file mode 100644 index 000000000..e80f62230 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Literals.h @@ -0,0 +1,198 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * Simple table used to translate a request + * opcode to the name of the X request. + */ + +static char *nxagentRequestLiteral[] = +{ + "None", + "CreateWindow", + "ChangeWindowAttributes", + "GetWindowAttributes", + "DestroyWindow", + "DestroySubwindows", + "ChangeSaveSet", + "ReparentWindow", + "MapWindow", + "MapSubwindows", + "UnmapWindow", + "UnmapSubwindows", + "ConfigureWindow", + "CirculateWindow", + "GetGeometry", + "QueryTree", + "InternAtom", + "GetAtomName", + "ChangeProperty", + "DeleteProperty", + "GetProperty", + "ListProperties", + "SetSelectionOwner", + "GetSelectionOwner", + "ConvertSelection", + "SendEvent", + "GrabPointer", + "UngrabPointer", + "GrabButton", + "UngrabButton", + "ChangeActivePointerGrab", + "GrabKeyboard", + "UngrabKeyboard", + "GrabKey", + "UngrabKey", + "AllowEvents", + "GrabServer", + "UngrabServer", + "QueryPointer", + "GetMotionEvents", + "TranslateCoords", + "WarpPointer", + "SetInputFocus", + "GetInputFocus", + "QueryKeymap", + "OpenFont", + "CloseFont", + "QueryFont", + "QueryTextExtents", + "ListFonts", + "ListFontsWithInfo", + "SetFontPath", + "GetFontPath", + "CreatePixmap", + "FreePixmap", + "CreateGC", + "ChangeGC", + "CopyGC", + "SetDashes", + "SetClipRectangles", + "FreeGC", + "ClearArea", + "CopyArea", + "CopyPlane", + "PolyPoint", + "PolyLine", + "PolySegment", + "PolyRectangle", + "PolyArc", + "FillPoly", + "PolyFillRectangle", + "PolyFillArc", + "PutImage", + "GetImage", + "PolyText8", + "PolyText16", + "ImageText8", + "ImageText16", + "CreateColormap", + "FreeColormap", + "CopyColormapAndFree", + "InstallColormap", + "UninstallColormap", + "ListInstalledColormaps", + "AllocColor", + "AllocNamedColor", + "AllocColorCells", + "AllocColorPlanes", + "FreeColors", + "StoreColors", + "StoreNamedColor", + "QueryColors", + "LookupColor", + "CreateCursor", + "CreateGlyphCursor", + "FreeCursor", + "RecolorCursor", + "QueryBestSize", + "QueryExtension", + "ListExtensions", + "ChangeKeyboardMapping", + "GetKeyboardMapping", + "ChangeKeyboardControl", + "GetKeyboardControl", + "Bell", + "ChangePointerControl", + "GetPointerControl", + "SetScreenSaver", + "GetScreenSaver", + "ChangeHosts", + "ListHosts", + "SetAccessControl", + "SetCloseDownMode", + "KillClient", + "RotateProperties", + "ForceScreenSaver", + "SetPointerMapping", + "GetPointerMapping", + "SetModifierMapping", + "GetModifierMapping", + "NoOperation" +}; + +static char *nxagentRenderRequestLiteral[] = +{ + "RenderQueryVersion", + "RenderQueryPictFormats", + "RenderQueryPictIndexValues", + "RenderQueryDithers", + "RenderCreatePicture", + "RenderChangePicture", + "RenderSetPictureClipRectangles", + "RenderFreePicture", + "RenderComposite", + "RenderScale", + "RenderTrapezoids", + "RenderTriangles", + "RenderTriStrip", + "RenderTriFan", + "RenderColorTrapezoids", + "RenderColorTriangles", + "RenderTransform", + "RenderCreateGlyphSet", + "RenderReferenceGlyphSet", + "RenderFreeGlyphSet", + "RenderAddGlyphs", + "RenderAddGlyphsFromPicture", + "RenderFreeGlyphs", + "RenderCompositeGlyphs", + "RenderCompositeGlyphs", + "RenderCompositeGlyphs", + "RenderFillRectangles", + "RenderCreateCursor", + "RenderSetPictureTransform", + "RenderQueryFilters", + "RenderSetPictureFilter", + "RenderCreateAnimCursor", + "RenderAddTraps", + "RenderCreateSolidFill", + "RenderCreateLinearGradient", + "RenderCreateRadialGradient", + "RenderCreateConicalGradient" +}; + +static char *nxagentShmRequestLiteral[] = +{ + "ShmQueryVersion", + "ShmAttach", + "ShmDetach", + "ShmPutImage", + "ShmGetImage", + "ShmCreatePixmap" +}; + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Millis.c b/nx-X11/programs/Xserver/hw/nxagent/Millis.c new file mode 100644 index 000000000..38435d9a8 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Millis.c @@ -0,0 +1,70 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include +#include + +#include "Xos.h" +#include "Millis.h" + +#ifdef DDXTIME + +CARD32 GetTimeInMillis() +{ + struct timeval ts; + + X_GETTIMEOFDAY(&ts); + + return(ts.tv_sec * 1000) + (ts.tv_usec / 1000); +} + +#endif + +const char *GetTimeAsString() +{ + char *value; + + struct timeval ts; + + X_GETTIMEOFDAY(&ts); + + value = ctime((time_t *) &ts.tv_sec); + + *(value + strlen(value) - 1) = '\0'; + + return value; +} + +const char *GetTimeInMillisAsString() +{ + char *value; + + char tb[25]; + + struct timeval ts; + + X_GETTIMEOFDAY(&ts); + + value = ctime((time_t *) &ts.tv_sec); + + sprintf(tb, "%.8s:%3.3f", value + 11, + (float) ts.tv_usec / 1000); + + strncpy(value, tb, 24); + + return value; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Millis.h b/nx-X11/programs/Xserver/hw/nxagent/Millis.h new file mode 100644 index 000000000..8ee380ae1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Millis.h @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Millis_H__ +#define __Millis_H__ + +#include "Xmd.h" + +CARD32 GetTimeInMillis(void); + +const char *GetTimeInMillisAsString(void); + +const char *GetTimeAsString(void); + +#endif /* __Millis_H__ */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXcomposite.c b/nx-X11/programs/Xserver/hw/nxagent/NXcomposite.c new file mode 100644 index 000000000..09bdaeb31 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXcomposite.c @@ -0,0 +1,359 @@ +#ifndef NXAGENT_UPGRADE + +/* + * $Id: Xcomposite.c,v 1.2 2005/07/03 07:00:56 daniels Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef NXAGENT_SERVER + +#include "NXcompositeint.h" + +#else + +#include "compositeint.h" + +#endif + +XCompositeExtInfo XCompositeExtensionInfo; + +const char XCompositeExtensionName[] = COMPOSITE_NAME; + +/* + * XCompositeExtRemoveDisplay - remove the indicated display from the + * extension object. (Replaces XextRemoveDisplay.) + */ +static int +XCompositeExtRemoveDisplay (XCompositeExtInfo *extinfo, Display *dpy) +{ + XCompositeExtDisplayInfo *info, *prev; + + /* + * locate this display and its back link so that it can be removed + */ + _XLockMutex(_Xglobal_lock); + prev = NULL; + for (info = extinfo->head; info; info = info->next) { + if (info->display == dpy) break; + prev = info; + } + if (!info) { + _XUnlockMutex(_Xglobal_lock); + return 0; /* hmm, actually an error */ + } + + /* + * remove the display from the list; handles going to zero + */ + if (prev) + prev->next = info->next; + else + extinfo->head = info->next; + + extinfo->ndisplays--; + if (info == extinfo->cur) extinfo->cur = NULL; /* flush cache */ + _XUnlockMutex(_Xglobal_lock); + + Xfree ((char *) info); + return 1; +} + +static int +XCompositeCloseDisplay (Display *dpy, XExtCodes *codes) +{ + return XCompositeExtRemoveDisplay (&XCompositeExtensionInfo, dpy); +} + +/* + * XCompositeExtAddDisplay - add a display to this extension. (Replaces + * XextAddDisplay) + */ +static XCompositeExtDisplayInfo * +XCompositeExtAddDisplay (XCompositeExtInfo *extinfo, + Display *dpy, + const char *ext_name) +{ + XCompositeExtDisplayInfo *info; + + #ifndef NXAGENT_SERVER + + int ev; + + #endif + + info = (XCompositeExtDisplayInfo *) Xmalloc (sizeof (XCompositeExtDisplayInfo)); + if (!info) return NULL; + info->display = dpy; + + info->codes = XInitExtension (dpy, ext_name); + + /* + * if the server has the extension, then we can initialize the + * appropriate function vectors + */ + if (info->codes) { + xCompositeQueryVersionReply rep; + xCompositeQueryVersionReq *req; + XESetCloseDisplay (dpy, info->codes->extension, + XCompositeCloseDisplay); + /* + * Get the version info + */ + LockDisplay (dpy); + GetReq (CompositeQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->compositeReqType = X_CompositeQueryVersion; + req->majorVersion = COMPOSITE_MAJOR; + req->minorVersion = COMPOSITE_MINOR; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) + { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + info->major_version = rep.majorVersion; + info->minor_version = rep.minorVersion; + UnlockDisplay (dpy); + } else { + /* The server doesn't have this extension. + * Use a private Xlib-internal extension to hang the close_display + * hook on so that the "cache" (extinfo->cur) is properly cleaned. + * (XBUG 7955) + */ + XExtCodes *codes = XAddExtension(dpy); + if (!codes) { + XFree(info); + return NULL; + } + XESetCloseDisplay (dpy, codes->extension, XCompositeCloseDisplay); + } + + /* + * now, chain it onto the list + */ + _XLockMutex(_Xglobal_lock); + info->next = extinfo->head; + extinfo->head = info; + extinfo->cur = info; + extinfo->ndisplays++; + _XUnlockMutex(_Xglobal_lock); + return info; +} + +/* + * XCompositeExtFindDisplay - look for a display in this extension; keeps a + * cache of the most-recently used for efficiency. (Replaces + * XextFindDisplay.) + */ +static XCompositeExtDisplayInfo * +XCompositeExtFindDisplay (XCompositeExtInfo *extinfo, + Display *dpy) +{ + XCompositeExtDisplayInfo *info; + + /* + * see if this was the most recently accessed display + */ + if ((info = extinfo->cur) && info->display == dpy) + return info; + + /* + * look for display in list + */ + _XLockMutex(_Xglobal_lock); + for (info = extinfo->head; info; info = info->next) { + if (info->display == dpy) { + extinfo->cur = info; /* cache most recently used */ + _XUnlockMutex(_Xglobal_lock); + return info; + } + } + _XUnlockMutex(_Xglobal_lock); + + return NULL; +} + +XCompositeExtDisplayInfo * +XCompositeFindDisplay (Display *dpy) +{ + XCompositeExtDisplayInfo *info; + + info = XCompositeExtFindDisplay (&XCompositeExtensionInfo, dpy); + if (!info) + info = XCompositeExtAddDisplay (&XCompositeExtensionInfo, dpy, + XCompositeExtensionName); + return info; +} + + +Bool +XCompositeQueryExtension (Display *dpy, int *event_basep, int *error_basep) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + + if (XCompositeHasExtension(info)) + { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } + else + return False; +} + +Status +XCompositeQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + + XCompositeCheckExtension (dpy, info, 0); + *major_versionp = info->major_version; + *minor_versionp = info->minor_version; + UnlockDisplay (dpy); + SyncHandle (); + return 1; +} + +int +XCompositeVersion (void) +{ + return XCOMPOSITE_VERSION; +} + +void +XCompositeRedirectWindow (Display *dpy, Window window, int update) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + xCompositeRedirectWindowReq *req; + + XCompositeSimpleCheckExtension (dpy, info); + LockDisplay (dpy); + GetReq (CompositeRedirectWindow, req); + req->reqType = info->codes->major_opcode; + req->compositeReqType = X_CompositeRedirectWindow; + req->window = window; + req->update = update; + UnlockDisplay (dpy); + SyncHandle (); +} + +void +XCompositeRedirectSubwindows (Display *dpy, Window window, int update) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + xCompositeRedirectSubwindowsReq *req; + + XCompositeSimpleCheckExtension (dpy, info); + LockDisplay (dpy); + GetReq (CompositeRedirectSubwindows, req); + req->reqType = info->codes->major_opcode; + req->compositeReqType = X_CompositeRedirectSubwindows; + req->window = window; + req->update = update; + UnlockDisplay (dpy); + SyncHandle (); +} + +void +XCompositeUnredirectWindow (Display *dpy, Window window, int update) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + xCompositeUnredirectWindowReq *req; + + XCompositeSimpleCheckExtension (dpy, info); + LockDisplay (dpy); + GetReq (CompositeUnredirectWindow, req); + req->reqType = info->codes->major_opcode; + req->compositeReqType = X_CompositeUnredirectWindow; + req->window = window; + req->update = update; + UnlockDisplay (dpy); + SyncHandle (); +} + +void +XCompositeUnredirectSubwindows (Display *dpy, Window window, int update) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + xCompositeUnredirectSubwindowsReq *req; + + XCompositeSimpleCheckExtension (dpy, info); + LockDisplay (dpy); + GetReq (CompositeUnredirectSubwindows, req); + req->reqType = info->codes->major_opcode; + req->compositeReqType = X_CompositeUnredirectSubwindows; + req->window = window; + req->update = update; + UnlockDisplay (dpy); + SyncHandle (); +} + +XserverRegion +XCompositeCreateRegionFromBorderClip (Display *dpy, Window window) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + xCompositeCreateRegionFromBorderClipReq *req; + XserverRegion region; + + XCompositeCheckExtension (dpy, info, 0); + LockDisplay (dpy); + GetReq (CompositeCreateRegionFromBorderClip, req); + req->reqType = info->codes->major_opcode; + req->compositeReqType = X_CompositeCreateRegionFromBorderClip; + req->window = window; + region = req->region = XAllocID (dpy); + UnlockDisplay (dpy); + SyncHandle (); + + #ifdef NXAGENT_SERVER + + return region; + + #else + + return region; + + #endif +} + +Pixmap +XCompositeNameWindowPixmap (Display *dpy, Window window) +{ + XCompositeExtDisplayInfo *info = XCompositeFindDisplay (dpy); + xCompositeNameWindowPixmapReq *req; + Pixmap pixmap; + + XCompositeCheckExtension (dpy, info, 0); + LockDisplay (dpy); + GetReq (CompositeNameWindowPixmap, req); + req->reqType = info->codes->major_opcode; + req->compositeReqType = X_CompositeNameWindowPixmap; + req->window = window; + pixmap = req->pixmap = XAllocID (dpy); + UnlockDisplay (dpy); + SyncHandle (); + return pixmap; +} + +#endif /* #ifndef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXcomposite.h b/nx-X11/programs/Xserver/hw/nxagent/NXcomposite.h new file mode 100644 index 000000000..952e0d3e3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXcomposite.h @@ -0,0 +1,86 @@ +#ifndef NXAGENT_UPGRADE + +/* + * $Id: Xcomposite.h,v 1.3 2005/07/03 07:00:56 daniels Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _XCOMPOSITE_H_ +#define _XCOMPOSITE_H_ + +#ifdef NXAGENT_SERVER + +#define XserverRegion XID + +#include "NXcompositeext.h" + +#else + +#include +#include + +#endif + +#include + +/* + * This revision number also appears in configure.ac, they have + * to be manually synchronized + */ +#define XCOMPOSITE_MAJOR COMPOSITE_MAJOR +#define XCOMPOSITE_MINOR COMPOSITE_MINOR +#define XCOMPOSITE_REVISION 0 +#define XCOMPOSITE_VERSION ((XCOMPOSITE_MAJOR * 10000) + (XCOMPOSITE_MINOR * 100) + (XCOMPOSITE_REVISION)) + +_XFUNCPROTOBEGIN + +Bool XCompositeQueryExtension (Display *dpy, int *event_basep, int *error_basep); + +Status XCompositeQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp); + +int XCompositeVersion (void); + +void +XCompositeRedirectWindow (Display *dpy, Window window, int update); + +void +XCompositeRedirectSubwindows (Display *dpy, Window window, int update); + +void +XCompositeUnredirectWindow (Display *dpy, Window window, int update); + +void +XCompositeUnredirectSubwindows (Display *dpy, Window window, int update); + +XserverRegion +XCompositeCreateRegionFromBorderClip (Display *dpy, Window window); + +Pixmap +XCompositeNameWindowPixmap (Display *dpy, Window window); + +_XFUNCPROTOEND + +#endif /* _XCOMPOSITE_H_ */ + +#endif /* #ifndef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h new file mode 100644 index 000000000..a22335153 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h @@ -0,0 +1,55 @@ +#ifndef NXAGENT_UPGRADE + +/* + * $Id: composite.h,v 1.4 2004/07/08 07:20:55 keithp Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _COMPOSITE_H_ +#define _COMPOSITE_H_ + +#ifndef NXAGENT_SERVER + +#include + +#endif + +#define COMPOSITE_NAME "Composite" +#define COMPOSITE_MAJOR 0 +#define COMPOSITE_MINOR 2 + +#define CompositeRedirectAutomatic 0 +#define CompositeRedirectManual 1 + +#define X_CompositeQueryVersion 0 +#define X_CompositeRedirectWindow 1 +#define X_CompositeRedirectSubwindows 2 +#define X_CompositeUnredirectWindow 3 +#define X_CompositeUnredirectSubwindows 4 +#define X_CompositeCreateRegionFromBorderClip 5 +#define X_CompositeNameWindowPixmap 6 + +#define CompositeNumberRequests (X_CompositeNameWindowPixmap + 1) + +#endif /* _COMPOSITE_H_ */ + +#endif /* #ifndef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXcompositeint.h b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeint.h new file mode 100644 index 000000000..044335abb --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeint.h @@ -0,0 +1,76 @@ +#ifndef NXAGENT_UPGRADE + +/* + * $Id: xcompositeint.h,v 1.3 2005/07/12 03:10:35 keithp Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _XDAMAGEINT_H_ +#define _XDAMAGEINT_H_ + +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include +#include +#include + +#ifdef NXAGENT_SERVER +#include "NXcompositeproto.h" +#include "NXcomposite.h" +#else +#include +#include +#endif + +typedef struct _XCompositeExtDisplayInfo { + struct _XCompositeExtDisplayInfo *next; /* keep a linked list */ + Display *display; /* which display this is */ + XExtCodes *codes; /* the extension protocol codes */ + int major_version; /* -1 means we don't know */ + int minor_version; /* -1 means we don't know */ +} XCompositeExtDisplayInfo; + +/* replaces XExtensionInfo */ +typedef struct _XCompositeExtInfo { + XCompositeExtDisplayInfo *head; /* start of the list */ + XCompositeExtDisplayInfo *cur; /* most recently used */ + int ndisplays; /* number of displays */ +} XCompositeExtInfo; + +extern XCompositeExtInfo XCompositeExtensionInfo; +extern const char XCompositeExtensionName[]; + +XCompositeExtDisplayInfo * +XCompositeFindDisplay (Display *dpy); + +#define XCompositeHasExtension(i) ((i) && ((i)->codes)) + +#define XCompositeCheckExtension(dpy,i,val) \ + if (!XCompositeHasExtension(i)) { return val; } + +#define XCompositeSimpleCheckExtension(dpy,i) \ + if (!XCompositeHasExtension(i)) { return; } + +#endif /* _XDAMAGEINT_H_ */ + +#endif /* #ifndef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXcompositeproto.h b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeproto.h new file mode 100644 index 000000000..cd31c7c8c --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeproto.h @@ -0,0 +1,148 @@ +#ifndef NXAGENT_UPGRADE + +/* + * $Id: compositeproto.h,v 1.4 2004/07/08 07:20:55 keithp Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _COMPOSITEPROTO_H_ +#define _COMPOSITEPROTO_H_ + +#include + +#ifdef NXAGENT_SERVER + +#include "NXcomposite.h" + +#else + +#include + +#endif + +#define Window CARD32 +#define Region CARD32 + +/* + * requests and replies + */ +typedef struct { + CARD8 reqType; + CARD8 compositeReqType; + CARD16 length B16; + CARD32 majorVersion B32; + CARD32 minorVersion B32; +} xCompositeQueryVersionReq; + +#define sz_xCompositeQueryVersionReq 12 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 majorVersion B32; + CARD32 minorVersion B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xCompositeQueryVersionReply; + +#define sz_xCompositeQueryVersionReply 32 + +typedef struct { + CARD8 reqType; + CARD8 compositeReqType; + CARD16 length B16; + Window window B32; + CARD8 update; + CARD8 pad1; + CARD16 pad2 B16; +} xCompositeRedirectWindowReq; + +#define sz_xCompositeRedirectWindowReq 12 + +typedef struct { + CARD8 reqType; + CARD8 compositeReqType; + CARD16 length B16; + Window window B32; + CARD8 update; + CARD8 pad1; + CARD16 pad2 B16; +} xCompositeRedirectSubwindowsReq; + +#define sz_xCompositeRedirectSubwindowsReq 12 + +typedef struct { + CARD8 reqType; + CARD8 compositeReqType; + CARD16 length B16; + Window window B32; + CARD8 update; + CARD8 pad1; + CARD16 pad2 B16; +} xCompositeUnredirectWindowReq; + +#define sz_xCompositeUnredirectWindowReq 12 + +typedef struct { + CARD8 reqType; + CARD8 compositeReqType; + CARD16 length B16; + Window window B32; + CARD8 update; + CARD8 pad1; + CARD16 pad2 B16; +} xCompositeUnredirectSubwindowsReq; + +#define sz_xCompositeUnredirectSubwindowsReq 12 + +typedef struct { + CARD8 reqType; + CARD8 compositeReqType; + CARD16 length B16; + Region region B32; + Window window B32; +} xCompositeCreateRegionFromBorderClipReq; + +#define sz_xCompositeCreateRegionFromBorderClipReq 12 + +/* Version 0.2 additions */ + +typedef struct { + CARD8 reqType; + CARD8 compositeReqType; + CARD16 length; + Window window B32; + Pixmap pixmap B32; +} xCompositeNameWindowPixmapReq; + +#define sz_xCompositeNameWindowPixmapReq 12 + +#undef Window +#undef Region + +#endif /* _COMPOSITEPROTO_H_ */ + +#endif /* #ifndef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdamage.c b/nx-X11/programs/Xserver/hw/nxagent/NXdamage.c new file mode 100644 index 000000000..8f43680b2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdamage.c @@ -0,0 +1,5 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXdamage.c" + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c new file mode 100644 index 000000000..90da743a2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c @@ -0,0 +1,4716 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXdispatch.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) 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. * +* * +*****************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.29 2003/01/12 02:44:26 dawes Exp $ */ + +#ifdef PANORAMIX_DEBUG +#include +int ProcInitialConnection(); +#endif + +#ifdef __sun +#define False 0 +#define True 1 +#endif + +#define GC XlibGC +#include +#undef GC + +#include "windowstr.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#ifdef XKB +#define XKB_IN_SERVER +#include "inputstr.h" +#include "XKBsrv.h" +#endif + +#include "Atoms.h" +#include "Splash.h" +#include "Client.h" +#include "Clipboard.h" +#include "Reconnect.h" +#include "Millis.h" +#include "Font.h" +#include "Shadow.h" +#include "Handlers.h" + +const int nxagentMaxFontNames = 10000; + +char dispatchExceptionAtReset = DE_RESET; + +/* + * This allows the agent to exit if no + * client is connected within a timeout. +*/ + +int nxagentClients = 0; + +void nxagentWaitDisplay(void); + +void nxagentListRemoteFonts(const char *, int); + +unsigned int nxagentWMtimeout = 0; +Bool nxagentWMPassed = 0; + +/* + * Timeouts based on screen saver time. + */ + +int nxagentAutoDisconnectTimeout = 0; + +#ifdef LBX +#include "../../lbx/lbxserve.h" +#endif + +#include "Xatom.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef WATCH + +/* + * Log begin and end of the important handlers. + */ + +#undef BLOCKS + +#ifdef WATCH +#include "unistd.h" +#endif + +#ifdef TEST +#include "Literals.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; + +Selection *CurrentSelections; +int NumCurrentSelections; + +extern WindowPtr nxagentViewportFrameLeft; +extern WindowPtr nxagentViewportFrameRight; +extern WindowPtr nxagentViewportFrameAbove; +extern WindowPtr nxagentViewportFrameBelow; + +#define IsViewportFrame(pWin) ((pWin) == nxagentViewportFrameLeft || \ + (pWin) == nxagentViewportFrameRight || \ + (pWin) == nxagentViewportFrameAbove || \ + (pWin) == nxagentViewportFrameBelow) + +extern int nxagentMaxAllowedResets; + +extern int nxagentFindClientResource(int, RESTYPE, pointer); + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +static void KillAllClients( +#if NeedFunctionPrototypes + void +#endif +); + +static void DeleteClientFromAnySelections( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; +char dispatchException = 0; +char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(c0, c1) + HWEventQueuePtr c0, c1; +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; + +#ifdef NXAGENT_CLIPBOARD + { + Selection *newsels; + newsels = (Selection *)xalloc(2 * sizeof(Selection)); + if (!newsels) + return; + NumCurrentSelections += 2; + CurrentSelections = newsels; + + CurrentSelections[0].selection = XA_PRIMARY; + CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[0].window = WindowTable[0]->drawable.id; + CurrentSelections[0].pWin = NULL; + CurrentSelections[0].client = NullClient; + + CurrentSelections[1].selection = MakeAtom("CLIPBOARD", 9, 1); + CurrentSelections[1].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[1].window = WindowTable[0]->drawable.id; + CurrentSelections[1].pWin = NULL; + CurrentSelections[1].client = NullClient; + } +#endif + +} + +void +FlushClientCaches(id) + XID id; +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; ilastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} +#ifdef SMART_SCHEDULE + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +/* + * Disable the SmartScheduler as it doesn't + * seem to work for us. + */ + +Bool SmartScheduleDisable = True; + +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +ClientPtr SmartLastClient; +int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; +int SmartScheduleClient(int *clientReady, int nready); + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); +void InitProcVectors(void); + +int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} +#endif + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; +#ifdef SMART_SCHEDULE + int start_tick; +#endif + + unsigned long currentDispatch = 0; + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + /* + * The agent initialization was successfully + * completed. We can now handle our clients. + */ + + if (serverGeneration > nxagentMaxAllowedResets) + { + fprintf(stderr, "Session: Session started at '%s'.\n", GetTimeAsString()); + + nxagentSessionState = SESSION_UP; + } + +#ifdef NXAGENT_ONSTART + + /* + * Set NX_WM property (used by NX client to identify + * the agent's window) three seconds since the first + * client connects. + */ + + nxagentWMtimeout = GetTimeInMillis() + 3000; + +#endif + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + #ifdef WATCH + + fprintf(stderr, "Dispatch: Watchpoint 12.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#3 1 352 bits (0 KB) -> 236 bits (0 KB) -> 352/1 -> 236/1 = 1.492:1 +#14 1 256 bits (0 KB) -> 101 bits (0 KB) -> 256/1 -> 101/1 = 2.535:1 +#16 1 256 bits (0 KB) -> 26 bits (0 KB) -> 256/1 -> 26/1 = 9.846:1 +#20 2 2 12256 bits (1 KB) -> 56 bits (0 KB) -> 6128/1 -> 28/1 = 218.857:1 +#43 1 256 bits (0 KB) -> 45 bits (0 KB) -> 256/1 -> 45/1 = 5.689:1 +#47 2 2 42304 bits (5 KB) -> 49 bits (0 KB) -> 21152/1 -> 24/1 = 863.347:1 +#98 1 256 bits (0 KB) -> 34 bits (0 KB) -> 256/1 -> 34/1 = 7.529:1 +*/ + + sleep(30); + + #endif + + #ifdef TEST + fprintf(stderr, "Dispatch: Value of dispatchException is [%x].\n", + dispatchException); + + fprintf(stderr, "Dispatch: Value of dispatchExceptionAtReset is [%x].\n", + dispatchExceptionAtReset); + #endif + + if (!(dispatchException & DE_TERMINATE)) + dispatchException = 0; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + /* + * Ensure we remove the splash after the timeout. + * Initializing clientReady[0] to -1 will tell + * WaitForSomething() to yield control after the + * timeout set in clientReady[1]. + */ + + clientReady[0] = 0; + + if (nxagentSplashWindow != None || (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0)) + { + #ifdef TEST + fprintf(stderr, "******Dispatch: Requesting a timeout of [%d] Ms.\n", + NXAGENT_WAKEUP); + #endif + + clientReady[0] = -1; + clientReady[1] = NXAGENT_WAKEUP; + } + + #ifdef BLOCKS + fprintf(stderr, "[End dispatch]\n"); + #endif + + nready = WaitForSomething(clientReady); + + #ifdef BLOCKS + fprintf(stderr, "[Begin dispatch]\n"); + #endif + + #ifdef TEST + fprintf(stderr, "******Dispatch: Running with [%d] clients ready.\n", + nready); + #endif + + #ifdef NXAGENT_ONSTART + + currentDispatch = GetTimeInMillis(); + + /* + * If the timeout is expired set the + * selection informing the NX client + * that the agent is ready. + */ + + if (!nxagentWMPassed && (nxagentWMtimeout < currentDispatch)) + { + nxagentRemoveSplashWindow(NULL); + } + + nxagentClients = nClients; + + #endif + +#ifdef SMART_SCHEDULE + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } +#endif + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; +#ifdef SMART_SCHEDULE + start_tick = SmartScheduleTime; +#endif + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } +#endif + /* now, finally, deal with client requests */ + + #ifdef TEST + fprintf(stderr, "******Dispatch: Reading request from client [%d].\n", + client->index); + #endif + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } +#ifdef NXAGENT_SERVER + + #ifdef TEST + + else + { + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Read [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d].\n", MAJOROP, *((char *) client->requestBuffer + 1), + client->req_len << 2, client->index); + } + else + { + fprintf(stderr, "******Dispatch: Read [%s] request OPCODE#%d size [%d] client [%d].\n", + nxagentRequestLiteral[MAJOROP], MAJOROP, client->req_len << 2, + client->index); + } + } + + #endif +#endif + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (MAX_BIG_REQUEST_SIZE << 2)) + result = BadLength; + else +#ifdef NXAGENT_SERVER + { + result = (* client->requestVector[MAJOROP])(client); + + #ifdef TEST + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Handled [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d] result [%d].\n", MAJOROP, + *((char *) client->requestBuffer + 1), client->req_len << 2, + client->index, result); + } + else + { + fprintf(stderr, "******Dispatch: Handled [%s] request OPCODE#%d size [%d] client [%d] " + "result [%d].\n", nxagentRequestLiteral[MAJOROP], MAJOROP, + client->req_len << 2, client->index, result); + } + + #endif + + /* + * Can set isItTimeToYield to force + * the dispatcher to pay attention + * to another client. + */ + + nxagentDispatchHandler(client, client->req_len << 2, 0); + } +#else + result = (* client->requestVector[MAJOROP])(client); +#endif + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } + + if ((dispatchException & DE_RESET) && + (serverGeneration > nxagentMaxAllowedResets)) + { + dispatchException &= ~DE_RESET; + dispatchException |= DE_TERMINATE; + + fprintf(stderr, "Info: Reached threshold of maximum allowed resets.\n"); + } + + nxagentResetAtomMap(); + + if (serverGeneration > nxagentMaxAllowedResets) + { + /* + * The session is terminating. Force an I/O + * error on the display and wait until the + * NX transport is gone. + */ + + fprintf(stderr, "Session: Terminating session at '%s'.\n", GetTimeAsString()); + + nxagentWaitDisplay(); + + fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString()); + } + + if (nxagentOption(Shadow)) + { + NXShadowDestroy(); + } + + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +/*ARGSUSED*/ +int +ProcBadRequest(client) + ClientPtr client; +{ + return (BadRequest); +} + +int +ProcCreateWindow(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + + if (!nxagentWMPassed) + { + nxagentRemoveSplashWindow(pWin); + } + + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + + return(client->noClientException); +} + +int +ProcUnmapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(client, rep) + register ClientPtr client; + xGetGeometryReply *rep; +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(client) + register ClientPtr client; +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(client) + register ClientPtr client; +{ + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + numChildren++; + } + } + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + childIDs[curChild++] = pChild->drawable.id; + } + } + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(client) + register ClientPtr client; +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(client) + register ClientPtr client; +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(client) + register ClientPtr client; +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + +#ifdef NXAGENT_CLIPBOARD + if ((CurrentSelections[i].pWin != NULL) && + (nxagentOption(Clipboard) != ClipboardNone) && + ((CurrentSelections[i].selection == XA_PRIMARY) || + (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0)))) + { + nxagentSetSelectionOwner(&CurrentSelections[i]); + } +#endif + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(client) + register ClientPtr client; +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + +#ifdef NXAGENT_CLIPBOARD + if (((stuff->selection == XA_PRIMARY) || + (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) && + nxagentOption(Clipboard) != ClipboardNone) + { + int i = 0; + + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + + if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None)) + { + if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor, + stuff->property, stuff->target, stuff->time)) + { + return (client->noClientException); + } + } + } +#endif + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient) +#ifdef XCSECURITY + && (!client->CheckAccess || + (* client->CheckAccess)(client, CurrentSelections[i].window, + RT_WINDOW, SecurityReadAccess, + CurrentSelections[i].pWin)) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +#if NeedFunctionPrototypes +UngrabServer(ClientPtr client) +#else +UngrabServer(client) + ClientPtr client; +#endif +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(client) + register ClientPtr client; +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(client) + register ClientPtr client; +{ + int err; + char fontReq[256]; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + + memcpy(fontReq,(char *)&stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + fontReq[stuff->nbytes]=0; + if (strchr(fontReq,'*') || strchr(fontReq,'?')) + { + extern int nxOpenFont(ClientPtr, XID, Mask, unsigned, char*); +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ProcOpenFont try to find a common font with font pattern=%s\n",fontReq); +#endif + nxagentListRemoteFonts(fontReq, nxagentMaxFontNames); + err = nxOpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + } + else + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(client) + register ClientPtr client; +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if (pFont != (FontPtr)NULL) + { + #ifdef NXAGENT_SERVER + + /* + * When a client closes a font the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this font looping through the + * resources. + */ + + if (pFont -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_FONT, pFont) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcCloseFont: Switching resource for font at [%p].\n", + (void *) pFont); + #endif + + nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index); + + AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont); + + } + #ifdef TEST + else + { + fprintf(stderr, "ProcCloseFont: Found duplicated font at [%p], " + "resource switching skipped.\n", (void *) pFont); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(client) + register ClientPtr client; +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + + pFont = NULL; + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + +/* test +{ + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if (props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return (BadFont); + + name = (char *)NameForAtom(value_atom); + fprintf(stderr, "QueryFont: font name [%s]\n",name); +} + end test */ + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = NULL; + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(client) + register ClientPtr client; +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(client) + register ClientPtr client; +{ + char tmp[256]; + + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames : stuff->maxNames); + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(client) + register ClientPtr client; +{ + char tmp[256]; + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont with info request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames :stuff->maxNames); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/*ARGSUSED*/ +int +dixDestroyPixmap(value, pid) + pointer value; /* must conform to DeleteType */ + XID pid; +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + #ifdef NXAGENT_SERVER + + /* + * When a client releases a pixmap the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this pixmap looping through the + * resources. + */ + + if (pMap -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_PIXMAP, pMap) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcFreePixmap: Switching resource for pixmap at [%p].\n", + (void *) pMap); + #endif + + nxagentPixmapPriv(pMap) -> mid = FakeClientID(serverClient -> index); + + AddResource(nxagentPixmapPriv(pMap) -> mid, RT_NX_PIXMAP, pMap); + } + #ifdef TEST + else + { + fprintf(stderr, "ProcFreePixmap: Found duplicated pixmap at [%p], " + "resource switching skipped.\n", (void *) pMap); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(client) + register ClientPtr client; +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(client) + register ClientPtr client; +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(client) + register ClientPtr client; +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(client) + register ClientPtr client; +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(client) + register ClientPtr client; +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(client) + register ClientPtr client; +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(client) + register ClientPtr client; +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(client) + register ClientPtr client; +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(client) + register ClientPtr client; +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + { + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyLine(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + { + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolySegment(client) + register ClientPtr client; +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + { + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyRectangle (client) + register ClientPtr client; +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + { + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcFillPoly(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + { + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyFillRectangle(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + + if (things) + { + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyFillArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(client) + register ClientPtr client; +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return (client->noClientException); +} + + +int +DoGetImage(client, format, drawable, x, y, width, height, planemask, im_return) + register ClientPtr client; + Drawable drawable; + int format; + int x, y, width, height; + Mask planemask; + xGetImageReply **im_return; +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; + RegionPtr pVisibleRegion = NULL; + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XCSECURITY + if (client->trustLevel != XSecurityClientTrusted && + pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } +#ifdef XCSECURITY + if (pVisibleRegion) + REGION_DESTROY(pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(client) + register ClientPtr client; +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(client) + register ClientPtr client; +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(client) + register ClientPtr client; +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadValue); +} + +int +ProcFreeColormap(client) + register ClientPtr client; +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(client) + register ClientPtr client; +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(client) + register ClientPtr client; +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor(client) + register ClientPtr client; +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pmap, (xReq *) stuff)) + return Success; +#endif + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocNamedColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorCells request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorPlanes request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + { + #ifdef TEST + fprintf(stderr, "ProcCreateCursor: Created cursor at [%p].\n", (void *) pCursor); + #endif + + return (client->noClientException); + } + + return BadAlloc; +} + +int +ProcCreateGlyphCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor(client) + register ClientPtr client; +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (client) + register ClientPtr client; +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (client) + register ClientPtr client; +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to change our values. + */ + + #ifdef TEST + fprintf(stderr, "ProcSetScreenSaver: Called with timeout [%d] interval [%d] Blanking [%d] Exposure [%d].\n", + stuff -> timeout, stuff -> interval, blankingOption, exposureOption); + #endif + + if (nxagentOption(Timeout) == 0) + { + if (blankingOption == DefaultBlanking) + { + ScreenSaverBlanking = defaultScreenSaverBlanking; + } + else + { + ScreenSaverBlanking = blankingOption; + } + + if (exposureOption == DefaultExposures) + { + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + } + else + { + ScreenSaverAllowExposures = exposureOption; + } + + if (stuff->timeout >= 0) + { + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + } + else + { + ScreenSaverTime = defaultScreenSaverTime; + } + + if (stuff->interval >= 0) + { + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + } + else + { + ScreenSaverInterval = defaultScreenSaverInterval; + } + } + + #ifdef TEST + + else + { + fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n", + nxagentOption(Timeout)); + } + + #endif + + return (client->noClientException); +} + +int +ProcGetScreenSaver(client) + register ClientPtr client; +{ + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(client) + register ClientPtr client; +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(client) + register ClientPtr client; +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XCSECURITY + /* untrusted clients can't list hosts */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to list hosts\n", client->index); + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(client) + register ClientPtr client; +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(client) + register ClientPtr client; +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(client) + register ClientPtr client; +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(client) + register ClientPtr client; +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(client) + register ClientPtr client; +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to force the screen + * saver handler execution. + */ + + if (nxagentOption(Timeout) == 0) + { + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + } + + #ifdef TEST + + else + { + fprintf(stderr, "ProcForceScreenSaver: Ignoring the client request with mode [%d].\n", + stuff -> mode); + } + + #endif + + return client->noClientException; +} + +int ProcNoOperation(client) + register ClientPtr client; +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors(void) +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = ReplyNotSwappd; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +void +CloseDownClient(client) + register ClientPtr client; +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + /* + * There must be a better way to hook a + * call-back function to be called any + * time a client is going to be closed. + */ + + nxagentClearClipboard(client, NULL); + + /* + * Need to reset the karma counter and + * get rid of the pending sync replies. + */ + + nxagentWakeupByReset(client); + + /* + * Check if the client + * is a shadow nxagent. + */ + + nxagentCheckIfShadowAgent(client); + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); +#ifdef LBX + ProcessQTagZombies(); +#endif + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; +#ifdef SMART_SCHEDULE + SmartLastClient = NullClient; +#endif + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; icloseDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; icloseDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +void InitClient(client, i, ospriv) + ClientPtr client; + int i; + pointer ospriv; +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (pointer *)NULL; + client->noClientException = Success; +#ifdef LOG_DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef LBX + client->readRequest = StandardReadRequestFromClient; +#endif +#ifdef XCSECURITY + client->trustLevel = XSecurityClientTrusted; + client->CheckAccess = NULL; + client->authId = 0; +#endif +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +#ifdef SMART_SCHEDULE + client->smart_priority = 0; + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; +#endif +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +int +InitClientPrivates(client) + ClientPtr client; +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + + /* + * Initialize the private members. + */ + + nxagentInitClientPrivates(client); + + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr +NextAvailableClient(ospriv) + pointer ospriv; +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(client) + register ClientPtr client; +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +#ifdef LBX +void +IncrementClientCount() +{ + nClients++; +} +#endif + +int +SendConnSetup(client, reason) + register ClientPtr client; + char *reason; +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; icurrentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(client) + register ClientPtr client; +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +void +SendErrorToClient(client, majorCode, minorCode, resId, errorCode) + ClientPtr client; + unsigned int majorCode; + unsigned int minorCode; + XID resId; + int errorCode; +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(pWin) + WindowPtr pWin; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(client) + ClientPtr client; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(client) + ClientPtr client; +{ + client->noClientException = -1; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.NX.original new file mode 100644 index 000000000..90da743a2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.NX.original @@ -0,0 +1,4716 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXdispatch.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) 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. * +* * +*****************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.29 2003/01/12 02:44:26 dawes Exp $ */ + +#ifdef PANORAMIX_DEBUG +#include +int ProcInitialConnection(); +#endif + +#ifdef __sun +#define False 0 +#define True 1 +#endif + +#define GC XlibGC +#include +#undef GC + +#include "windowstr.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#ifdef XKB +#define XKB_IN_SERVER +#include "inputstr.h" +#include "XKBsrv.h" +#endif + +#include "Atoms.h" +#include "Splash.h" +#include "Client.h" +#include "Clipboard.h" +#include "Reconnect.h" +#include "Millis.h" +#include "Font.h" +#include "Shadow.h" +#include "Handlers.h" + +const int nxagentMaxFontNames = 10000; + +char dispatchExceptionAtReset = DE_RESET; + +/* + * This allows the agent to exit if no + * client is connected within a timeout. +*/ + +int nxagentClients = 0; + +void nxagentWaitDisplay(void); + +void nxagentListRemoteFonts(const char *, int); + +unsigned int nxagentWMtimeout = 0; +Bool nxagentWMPassed = 0; + +/* + * Timeouts based on screen saver time. + */ + +int nxagentAutoDisconnectTimeout = 0; + +#ifdef LBX +#include "../../lbx/lbxserve.h" +#endif + +#include "Xatom.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef WATCH + +/* + * Log begin and end of the important handlers. + */ + +#undef BLOCKS + +#ifdef WATCH +#include "unistd.h" +#endif + +#ifdef TEST +#include "Literals.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; + +Selection *CurrentSelections; +int NumCurrentSelections; + +extern WindowPtr nxagentViewportFrameLeft; +extern WindowPtr nxagentViewportFrameRight; +extern WindowPtr nxagentViewportFrameAbove; +extern WindowPtr nxagentViewportFrameBelow; + +#define IsViewportFrame(pWin) ((pWin) == nxagentViewportFrameLeft || \ + (pWin) == nxagentViewportFrameRight || \ + (pWin) == nxagentViewportFrameAbove || \ + (pWin) == nxagentViewportFrameBelow) + +extern int nxagentMaxAllowedResets; + +extern int nxagentFindClientResource(int, RESTYPE, pointer); + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +static void KillAllClients( +#if NeedFunctionPrototypes + void +#endif +); + +static void DeleteClientFromAnySelections( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; +char dispatchException = 0; +char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(c0, c1) + HWEventQueuePtr c0, c1; +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; + +#ifdef NXAGENT_CLIPBOARD + { + Selection *newsels; + newsels = (Selection *)xalloc(2 * sizeof(Selection)); + if (!newsels) + return; + NumCurrentSelections += 2; + CurrentSelections = newsels; + + CurrentSelections[0].selection = XA_PRIMARY; + CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[0].window = WindowTable[0]->drawable.id; + CurrentSelections[0].pWin = NULL; + CurrentSelections[0].client = NullClient; + + CurrentSelections[1].selection = MakeAtom("CLIPBOARD", 9, 1); + CurrentSelections[1].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[1].window = WindowTable[0]->drawable.id; + CurrentSelections[1].pWin = NULL; + CurrentSelections[1].client = NullClient; + } +#endif + +} + +void +FlushClientCaches(id) + XID id; +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; ilastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} +#ifdef SMART_SCHEDULE + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +/* + * Disable the SmartScheduler as it doesn't + * seem to work for us. + */ + +Bool SmartScheduleDisable = True; + +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +ClientPtr SmartLastClient; +int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; +int SmartScheduleClient(int *clientReady, int nready); + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); +void InitProcVectors(void); + +int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} +#endif + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; +#ifdef SMART_SCHEDULE + int start_tick; +#endif + + unsigned long currentDispatch = 0; + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + /* + * The agent initialization was successfully + * completed. We can now handle our clients. + */ + + if (serverGeneration > nxagentMaxAllowedResets) + { + fprintf(stderr, "Session: Session started at '%s'.\n", GetTimeAsString()); + + nxagentSessionState = SESSION_UP; + } + +#ifdef NXAGENT_ONSTART + + /* + * Set NX_WM property (used by NX client to identify + * the agent's window) three seconds since the first + * client connects. + */ + + nxagentWMtimeout = GetTimeInMillis() + 3000; + +#endif + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + #ifdef WATCH + + fprintf(stderr, "Dispatch: Watchpoint 12.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#3 1 352 bits (0 KB) -> 236 bits (0 KB) -> 352/1 -> 236/1 = 1.492:1 +#14 1 256 bits (0 KB) -> 101 bits (0 KB) -> 256/1 -> 101/1 = 2.535:1 +#16 1 256 bits (0 KB) -> 26 bits (0 KB) -> 256/1 -> 26/1 = 9.846:1 +#20 2 2 12256 bits (1 KB) -> 56 bits (0 KB) -> 6128/1 -> 28/1 = 218.857:1 +#43 1 256 bits (0 KB) -> 45 bits (0 KB) -> 256/1 -> 45/1 = 5.689:1 +#47 2 2 42304 bits (5 KB) -> 49 bits (0 KB) -> 21152/1 -> 24/1 = 863.347:1 +#98 1 256 bits (0 KB) -> 34 bits (0 KB) -> 256/1 -> 34/1 = 7.529:1 +*/ + + sleep(30); + + #endif + + #ifdef TEST + fprintf(stderr, "Dispatch: Value of dispatchException is [%x].\n", + dispatchException); + + fprintf(stderr, "Dispatch: Value of dispatchExceptionAtReset is [%x].\n", + dispatchExceptionAtReset); + #endif + + if (!(dispatchException & DE_TERMINATE)) + dispatchException = 0; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + /* + * Ensure we remove the splash after the timeout. + * Initializing clientReady[0] to -1 will tell + * WaitForSomething() to yield control after the + * timeout set in clientReady[1]. + */ + + clientReady[0] = 0; + + if (nxagentSplashWindow != None || (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0)) + { + #ifdef TEST + fprintf(stderr, "******Dispatch: Requesting a timeout of [%d] Ms.\n", + NXAGENT_WAKEUP); + #endif + + clientReady[0] = -1; + clientReady[1] = NXAGENT_WAKEUP; + } + + #ifdef BLOCKS + fprintf(stderr, "[End dispatch]\n"); + #endif + + nready = WaitForSomething(clientReady); + + #ifdef BLOCKS + fprintf(stderr, "[Begin dispatch]\n"); + #endif + + #ifdef TEST + fprintf(stderr, "******Dispatch: Running with [%d] clients ready.\n", + nready); + #endif + + #ifdef NXAGENT_ONSTART + + currentDispatch = GetTimeInMillis(); + + /* + * If the timeout is expired set the + * selection informing the NX client + * that the agent is ready. + */ + + if (!nxagentWMPassed && (nxagentWMtimeout < currentDispatch)) + { + nxagentRemoveSplashWindow(NULL); + } + + nxagentClients = nClients; + + #endif + +#ifdef SMART_SCHEDULE + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } +#endif + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; +#ifdef SMART_SCHEDULE + start_tick = SmartScheduleTime; +#endif + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } +#endif + /* now, finally, deal with client requests */ + + #ifdef TEST + fprintf(stderr, "******Dispatch: Reading request from client [%d].\n", + client->index); + #endif + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } +#ifdef NXAGENT_SERVER + + #ifdef TEST + + else + { + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Read [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d].\n", MAJOROP, *((char *) client->requestBuffer + 1), + client->req_len << 2, client->index); + } + else + { + fprintf(stderr, "******Dispatch: Read [%s] request OPCODE#%d size [%d] client [%d].\n", + nxagentRequestLiteral[MAJOROP], MAJOROP, client->req_len << 2, + client->index); + } + } + + #endif +#endif + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (MAX_BIG_REQUEST_SIZE << 2)) + result = BadLength; + else +#ifdef NXAGENT_SERVER + { + result = (* client->requestVector[MAJOROP])(client); + + #ifdef TEST + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Handled [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d] result [%d].\n", MAJOROP, + *((char *) client->requestBuffer + 1), client->req_len << 2, + client->index, result); + } + else + { + fprintf(stderr, "******Dispatch: Handled [%s] request OPCODE#%d size [%d] client [%d] " + "result [%d].\n", nxagentRequestLiteral[MAJOROP], MAJOROP, + client->req_len << 2, client->index, result); + } + + #endif + + /* + * Can set isItTimeToYield to force + * the dispatcher to pay attention + * to another client. + */ + + nxagentDispatchHandler(client, client->req_len << 2, 0); + } +#else + result = (* client->requestVector[MAJOROP])(client); +#endif + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } + + if ((dispatchException & DE_RESET) && + (serverGeneration > nxagentMaxAllowedResets)) + { + dispatchException &= ~DE_RESET; + dispatchException |= DE_TERMINATE; + + fprintf(stderr, "Info: Reached threshold of maximum allowed resets.\n"); + } + + nxagentResetAtomMap(); + + if (serverGeneration > nxagentMaxAllowedResets) + { + /* + * The session is terminating. Force an I/O + * error on the display and wait until the + * NX transport is gone. + */ + + fprintf(stderr, "Session: Terminating session at '%s'.\n", GetTimeAsString()); + + nxagentWaitDisplay(); + + fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString()); + } + + if (nxagentOption(Shadow)) + { + NXShadowDestroy(); + } + + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +/*ARGSUSED*/ +int +ProcBadRequest(client) + ClientPtr client; +{ + return (BadRequest); +} + +int +ProcCreateWindow(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + + if (!nxagentWMPassed) + { + nxagentRemoveSplashWindow(pWin); + } + + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + + return(client->noClientException); +} + +int +ProcUnmapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(client, rep) + register ClientPtr client; + xGetGeometryReply *rep; +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(client) + register ClientPtr client; +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(client) + register ClientPtr client; +{ + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + numChildren++; + } + } + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + childIDs[curChild++] = pChild->drawable.id; + } + } + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(client) + register ClientPtr client; +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(client) + register ClientPtr client; +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(client) + register ClientPtr client; +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + +#ifdef NXAGENT_CLIPBOARD + if ((CurrentSelections[i].pWin != NULL) && + (nxagentOption(Clipboard) != ClipboardNone) && + ((CurrentSelections[i].selection == XA_PRIMARY) || + (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0)))) + { + nxagentSetSelectionOwner(&CurrentSelections[i]); + } +#endif + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(client) + register ClientPtr client; +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + +#ifdef NXAGENT_CLIPBOARD + if (((stuff->selection == XA_PRIMARY) || + (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) && + nxagentOption(Clipboard) != ClipboardNone) + { + int i = 0; + + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + + if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None)) + { + if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor, + stuff->property, stuff->target, stuff->time)) + { + return (client->noClientException); + } + } + } +#endif + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient) +#ifdef XCSECURITY + && (!client->CheckAccess || + (* client->CheckAccess)(client, CurrentSelections[i].window, + RT_WINDOW, SecurityReadAccess, + CurrentSelections[i].pWin)) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +#if NeedFunctionPrototypes +UngrabServer(ClientPtr client) +#else +UngrabServer(client) + ClientPtr client; +#endif +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(client) + register ClientPtr client; +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(client) + register ClientPtr client; +{ + int err; + char fontReq[256]; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + + memcpy(fontReq,(char *)&stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + fontReq[stuff->nbytes]=0; + if (strchr(fontReq,'*') || strchr(fontReq,'?')) + { + extern int nxOpenFont(ClientPtr, XID, Mask, unsigned, char*); +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ProcOpenFont try to find a common font with font pattern=%s\n",fontReq); +#endif + nxagentListRemoteFonts(fontReq, nxagentMaxFontNames); + err = nxOpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + } + else + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(client) + register ClientPtr client; +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if (pFont != (FontPtr)NULL) + { + #ifdef NXAGENT_SERVER + + /* + * When a client closes a font the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this font looping through the + * resources. + */ + + if (pFont -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_FONT, pFont) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcCloseFont: Switching resource for font at [%p].\n", + (void *) pFont); + #endif + + nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index); + + AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont); + + } + #ifdef TEST + else + { + fprintf(stderr, "ProcCloseFont: Found duplicated font at [%p], " + "resource switching skipped.\n", (void *) pFont); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(client) + register ClientPtr client; +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + + pFont = NULL; + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + +/* test +{ + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if (props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return (BadFont); + + name = (char *)NameForAtom(value_atom); + fprintf(stderr, "QueryFont: font name [%s]\n",name); +} + end test */ + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = NULL; + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(client) + register ClientPtr client; +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(client) + register ClientPtr client; +{ + char tmp[256]; + + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames : stuff->maxNames); + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(client) + register ClientPtr client; +{ + char tmp[256]; + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont with info request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames :stuff->maxNames); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/*ARGSUSED*/ +int +dixDestroyPixmap(value, pid) + pointer value; /* must conform to DeleteType */ + XID pid; +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + #ifdef NXAGENT_SERVER + + /* + * When a client releases a pixmap the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this pixmap looping through the + * resources. + */ + + if (pMap -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_PIXMAP, pMap) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcFreePixmap: Switching resource for pixmap at [%p].\n", + (void *) pMap); + #endif + + nxagentPixmapPriv(pMap) -> mid = FakeClientID(serverClient -> index); + + AddResource(nxagentPixmapPriv(pMap) -> mid, RT_NX_PIXMAP, pMap); + } + #ifdef TEST + else + { + fprintf(stderr, "ProcFreePixmap: Found duplicated pixmap at [%p], " + "resource switching skipped.\n", (void *) pMap); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(client) + register ClientPtr client; +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(client) + register ClientPtr client; +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(client) + register ClientPtr client; +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(client) + register ClientPtr client; +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(client) + register ClientPtr client; +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(client) + register ClientPtr client; +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(client) + register ClientPtr client; +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(client) + register ClientPtr client; +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(client) + register ClientPtr client; +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + { + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyLine(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + { + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolySegment(client) + register ClientPtr client; +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + { + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyRectangle (client) + register ClientPtr client; +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + { + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcFillPoly(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + { + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyFillRectangle(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + + if (things) + { + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyFillArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(client) + register ClientPtr client; +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return (client->noClientException); +} + + +int +DoGetImage(client, format, drawable, x, y, width, height, planemask, im_return) + register ClientPtr client; + Drawable drawable; + int format; + int x, y, width, height; + Mask planemask; + xGetImageReply **im_return; +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; + RegionPtr pVisibleRegion = NULL; + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XCSECURITY + if (client->trustLevel != XSecurityClientTrusted && + pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } +#ifdef XCSECURITY + if (pVisibleRegion) + REGION_DESTROY(pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(client) + register ClientPtr client; +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(client) + register ClientPtr client; +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(client) + register ClientPtr client; +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadValue); +} + +int +ProcFreeColormap(client) + register ClientPtr client; +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(client) + register ClientPtr client; +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(client) + register ClientPtr client; +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor(client) + register ClientPtr client; +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pmap, (xReq *) stuff)) + return Success; +#endif + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocNamedColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorCells request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorPlanes request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + { + #ifdef TEST + fprintf(stderr, "ProcCreateCursor: Created cursor at [%p].\n", (void *) pCursor); + #endif + + return (client->noClientException); + } + + return BadAlloc; +} + +int +ProcCreateGlyphCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor(client) + register ClientPtr client; +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (client) + register ClientPtr client; +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (client) + register ClientPtr client; +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to change our values. + */ + + #ifdef TEST + fprintf(stderr, "ProcSetScreenSaver: Called with timeout [%d] interval [%d] Blanking [%d] Exposure [%d].\n", + stuff -> timeout, stuff -> interval, blankingOption, exposureOption); + #endif + + if (nxagentOption(Timeout) == 0) + { + if (blankingOption == DefaultBlanking) + { + ScreenSaverBlanking = defaultScreenSaverBlanking; + } + else + { + ScreenSaverBlanking = blankingOption; + } + + if (exposureOption == DefaultExposures) + { + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + } + else + { + ScreenSaverAllowExposures = exposureOption; + } + + if (stuff->timeout >= 0) + { + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + } + else + { + ScreenSaverTime = defaultScreenSaverTime; + } + + if (stuff->interval >= 0) + { + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + } + else + { + ScreenSaverInterval = defaultScreenSaverInterval; + } + } + + #ifdef TEST + + else + { + fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n", + nxagentOption(Timeout)); + } + + #endif + + return (client->noClientException); +} + +int +ProcGetScreenSaver(client) + register ClientPtr client; +{ + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(client) + register ClientPtr client; +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(client) + register ClientPtr client; +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XCSECURITY + /* untrusted clients can't list hosts */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to list hosts\n", client->index); + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(client) + register ClientPtr client; +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(client) + register ClientPtr client; +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(client) + register ClientPtr client; +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(client) + register ClientPtr client; +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(client) + register ClientPtr client; +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to force the screen + * saver handler execution. + */ + + if (nxagentOption(Timeout) == 0) + { + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + } + + #ifdef TEST + + else + { + fprintf(stderr, "ProcForceScreenSaver: Ignoring the client request with mode [%d].\n", + stuff -> mode); + } + + #endif + + return client->noClientException; +} + +int ProcNoOperation(client) + register ClientPtr client; +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors(void) +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = ReplyNotSwappd; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +void +CloseDownClient(client) + register ClientPtr client; +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + /* + * There must be a better way to hook a + * call-back function to be called any + * time a client is going to be closed. + */ + + nxagentClearClipboard(client, NULL); + + /* + * Need to reset the karma counter and + * get rid of the pending sync replies. + */ + + nxagentWakeupByReset(client); + + /* + * Check if the client + * is a shadow nxagent. + */ + + nxagentCheckIfShadowAgent(client); + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); +#ifdef LBX + ProcessQTagZombies(); +#endif + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; +#ifdef SMART_SCHEDULE + SmartLastClient = NullClient; +#endif + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; icloseDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; icloseDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +void InitClient(client, i, ospriv) + ClientPtr client; + int i; + pointer ospriv; +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (pointer *)NULL; + client->noClientException = Success; +#ifdef LOG_DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef LBX + client->readRequest = StandardReadRequestFromClient; +#endif +#ifdef XCSECURITY + client->trustLevel = XSecurityClientTrusted; + client->CheckAccess = NULL; + client->authId = 0; +#endif +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +#ifdef SMART_SCHEDULE + client->smart_priority = 0; + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; +#endif +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +int +InitClientPrivates(client) + ClientPtr client; +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + + /* + * Initialize the private members. + */ + + nxagentInitClientPrivates(client); + + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr +NextAvailableClient(ospriv) + pointer ospriv; +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(client) + register ClientPtr client; +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +#ifdef LBX +void +IncrementClientCount() +{ + nClients++; +} +#endif + +int +SendConnSetup(client, reason) + register ClientPtr client; + char *reason; +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; icurrentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(client) + register ClientPtr client; +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +void +SendErrorToClient(client, majorCode, minorCode, resId, errorCode) + ClientPtr client; + unsigned int majorCode; + unsigned int minorCode; + XID resId; + int errorCode; +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(pWin) + WindowPtr pWin; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(client) + ClientPtr client; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(client) + ClientPtr client; +{ + client->noClientException = -1; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.XF86.original new file mode 100644 index 000000000..a385a8b09 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.XF86.original @@ -0,0 +1,4110 @@ +/* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) 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. * +* * +*****************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.29 2003/01/12 02:44:26 dawes Exp $ */ + +#ifdef PANORAMIX_DEBUG +#include +int ProcInitialConnection(); +#endif + +#include "windowstr.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#ifdef XKB +#define XKB_IN_SERVER +#include "inputstr.h" +#include "XKBsrv.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; + +Selection *CurrentSelections; +int NumCurrentSelections; + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +static void KillAllClients( +#if NeedFunctionPrototypes + void +#endif +); + +static void DeleteClientFromAnySelections( +#if NeedFunctionPrototypes + ClientPtr /*client*/ +#endif +); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; +char dispatchException = 0; +char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(c0, c1) + HWEventQueuePtr c0, c1; +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; +} + +void +FlushClientCaches(id) + XID id; +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; ilastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} +#ifdef SMART_SCHEDULE + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +Bool SmartScheduleDisable; +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +ClientPtr SmartLastClient; +int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; +int SmartScheduleClient(int *clientReady, int nready); + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); +void InitProcVectors(void); + +int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} +#endif + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; +#ifdef SMART_SCHEDULE + int start_tick; +#endif + + #ifdef __DARWIN__ + extern char dispatchExceptionAtReset; + #endif + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + nready = WaitForSomething(clientReady); + +#ifdef SMART_SCHEDULE + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } +#endif + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; +#ifdef SMART_SCHEDULE + start_tick = SmartScheduleTime; +#endif + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } +#endif + /* now, finally, deal with client requests */ + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (MAX_BIG_REQUEST_SIZE << 2)) + result = BadLength; + else + result = (* client->requestVector[MAJOROP])(client); + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + + /* + * On Darwin we found that the it is not possible + * to get the correct keyboard layout unless it is + * set on the local machine, before the NX session + * is started, by using xmodmap. As we set the key- + * board locally, we must prevent the X server to + * reset, otherwise we would loose any local confi- + * guration. The code below is aimed at this. Note + * also that a statically compiled version of xmod- + * map is included in the MacOS/X package. + */ + + #ifdef __DARWIN__ + + if (dispatchException & DE_RESET ) + { + dispatchException &= ~DE_RESET; + + dispatchExceptionAtReset = DE_TERMINATE; + } + + #endif /* __DARWIN__ */ + + } + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +/*ARGSUSED*/ +int +ProcBadRequest(client) + ClientPtr client; +{ + return (BadRequest); +} + +int +ProcCreateWindow(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapSubwindows(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(client) + register ClientPtr client; +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(client, rep) + register ClientPtr client; + xGetGeometryReply *rep; +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(client) + register ClientPtr client; +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(client) + register ClientPtr client; +{ + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + numChildren++; + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + childIDs[curChild++] = pChild->drawable.id; + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(client) + register ClientPtr client; +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(client) + register ClientPtr client; +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(client) + register ClientPtr client; +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(client) + register ClientPtr client; +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) +#ifdef XCSECURITY + && (!client->CheckAccess || + (* client->CheckAccess)(client, CurrentSelections[i].window, + RT_WINDOW, SecurityReadAccess, + CurrentSelections[i].pWin)) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +#if NeedFunctionPrototypes +UngrabServer(ClientPtr client) +#else +UngrabServer(client) + ClientPtr client; +#endif +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(client) + register ClientPtr client; +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(client) + register ClientPtr client; +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(client) + register ClientPtr client; +{ + int err; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(client) + register ClientPtr client; +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if ( pFont != (FontPtr)NULL) /* id was valid */ + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(client) + register ClientPtr client; +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(client) + register ClientPtr client; +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(client) + register ClientPtr client; +{ + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(client) + register ClientPtr client; +{ + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/*ARGSUSED*/ +int +dixDestroyPixmap(value, pid) + pointer value; /* must conform to DeleteType */ + XID pid; +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(client) + register ClientPtr client; +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(client) + register ClientPtr client; +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(client) + register ClientPtr client; +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(client) + register ClientPtr client; +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(client) + register ClientPtr client; +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(client) + register ClientPtr client; +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(client) + register ClientPtr client; +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(client) + register ClientPtr client; +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(client) + register ClientPtr client; +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyLine(client) + register ClientPtr client; +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolySegment(client) + register ClientPtr client; +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyRectangle (client) + register ClientPtr client; +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +int +ProcFillPoly(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyFillRectangle(client) + register ClientPtr client; +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + + if (things) + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyFillArc(client) + register ClientPtr client; +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(client) + register ClientPtr client; +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return (client->noClientException); +} + + +int +DoGetImage(client, format, drawable, x, y, width, height, planemask, im_return) + register ClientPtr client; + Drawable drawable; + int format; + int x, y, width, height; + Mask planemask; + xGetImageReply **im_return; +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; + RegionPtr pVisibleRegion = NULL; + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XCSECURITY + if (client->trustLevel != XSecurityClientTrusted && + pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } +#ifdef XCSECURITY + if (pVisibleRegion) + REGION_DESTROY(pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(client) + register ClientPtr client; +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(client) + register ClientPtr client; +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(client) + register ClientPtr client; +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(client) + register ClientPtr client; +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadValue); +} + +int +ProcFreeColormap(client) + register ClientPtr client; +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(client) + register ClientPtr client; +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(client) + register ClientPtr client; +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor(client) + register ClientPtr client; +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pmap, (xReq *) stuff)) + return Success; +#endif + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocNamedColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorCells request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorPlanes request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(client) + register ClientPtr client; +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +int +ProcCreateGlyphCursor( client) + register ClientPtr client; +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor(client) + register ClientPtr client; +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (client) + register ClientPtr client; +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (client) + register ClientPtr client; +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + if (blankingOption == DefaultBlanking) + ScreenSaverBlanking = defaultScreenSaverBlanking; + else + ScreenSaverBlanking = blankingOption; + if (exposureOption == DefaultExposures) + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + else + ScreenSaverAllowExposures = exposureOption; + + if (stuff->timeout >= 0) + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + else + ScreenSaverTime = defaultScreenSaverTime; + if (stuff->interval >= 0) + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + else + ScreenSaverInterval = defaultScreenSaverInterval; + return (client->noClientException); +} + +int +ProcGetScreenSaver(client) + register ClientPtr client; +{ + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(client) + register ClientPtr client; +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(client) + register ClientPtr client; +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XCSECURITY + /* untrusted clients can't list hosts */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to list hosts\n", client->index); + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(client) + register ClientPtr client; +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(client) + register ClientPtr client; +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(client) + register ClientPtr client; +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(client) + register ClientPtr client; +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(client) + register ClientPtr client; +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(client) + register ClientPtr client; +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + return client->noClientException; +} + +int ProcNoOperation(client) + register ClientPtr client; +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors(void) +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = ReplyNotSwappd; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +char dispatchExceptionAtReset = DE_RESET; + +void +CloseDownClient(client) + register ClientPtr client; +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); +#ifdef LBX + ProcessQTagZombies(); +#endif + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; +#ifdef SMART_SCHEDULE + SmartLastClient = NullClient; +#endif + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; icloseDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; icloseDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +void InitClient(client, i, ospriv) + ClientPtr client; + int i; + pointer ospriv; +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (pointer *)NULL; + client->noClientException = Success; +#ifdef DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef LBX + client->readRequest = StandardReadRequestFromClient; +#endif +#ifdef XCSECURITY + client->trustLevel = XSecurityClientTrusted; + client->CheckAccess = NULL; + client->authId = 0; +#endif +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +#ifdef SMART_SCHEDULE + client->smart_priority = 0; + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; +#endif +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +int +InitClientPrivates(client) + ClientPtr client; +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr +NextAvailableClient(ospriv) + pointer ospriv; +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(client) + register ClientPtr client; +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +#ifdef LBX +void +IncrementClientCount() +{ + nClients++; +} +#endif + +int +SendConnSetup(client, reason) + register ClientPtr client; + char *reason; +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; icurrentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(client) + register ClientPtr client; +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +void +SendErrorToClient(client, majorCode, minorCode, resId, errorCode) + ClientPtr client; + unsigned int majorCode; + unsigned int minorCode; + XID resId; + int errorCode; +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(pWin) + WindowPtr pWin; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(client) + ClientPtr client; +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(client) + ClientPtr client; +{ + client->noClientException = -1; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c new file mode 100644 index 000000000..83103ffd6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c @@ -0,0 +1,2883 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXdixfonts.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.27 2003/02/15 03:47:05 dawes Exp $ */ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */ + +#define NEED_REPLIES +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +/* +#define NXAGENT_DEBUG +*/ + +#ifdef DEBUG +#include +#endif + +#include "Agent.h" +#include "Font.h" + +#ifndef NX_TRANS_SOCKET + +#define NX_TRANS_SOCKET + +#endif + +#ifdef NX_TRANS_SOCKET + +char _NXFontPath[1024]; + +/* + * Override the default font path and make + * it configurable at run time, based on + * the NX_FONT environment. + */ + +static const char *_NXGetFontPath(const char *path) +{ + const char *fontEnv; + + /* + * Check the environment only once. + */ + + if (*_NXFontPath != '\0') + { + return _NXFontPath; + } + + fontEnv = getenv("NX_FONT"); + + if (fontEnv != NULL && *fontEnv != '\0') + { + if (strlen(fontEnv) + 1 > 1024) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n"); +#endif + goto _NXGetFontPathError; + } + + strcpy(_NXFontPath, fontEnv); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; + } + +_NXGetFontPathError: + + strcpy(_NXFontPath, path); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; +} + +#endif + +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif + +#ifdef LBX +#include "lbxserve.h" +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include "xf86bigfont.h" +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + return BadName; + case BadFontPath: + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(defaultfontname) + char *defaultfontname; +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +/* ARGSUSED */ +void +FontWakeup(data, count, LastSelectMask) + pointer data; + int count; + pointer LastSelectMask; +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +#if NeedFunctionPrototypes +UseFPE(FontPathElementPtr fpe) +#else +UseFPE(fpe) + FontPathElementPtr fpe; +#endif +{ + fpe->refcount++; +} + +static void +#if NeedFunctionPrototypes +FreeFPE (FontPathElementPtr fpe) +#else +FreeFPE (fpe) + FontPathElementPtr fpe; +#endif +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +#if NeedFunctionPrototypes +doOpenFont(ClientPtr client, OFclosurePtr c) +#else +doOpenFont(client, c) + ClientPtr client; + OFclosurePtr c; +#endif +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe = NULL; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + char nxagentOrigFontName[256]; + int nxagentOrigFontNameLen; + + /* + * Decide at runtime what FontFormat to use. + */ + Mask FontFormat = + + ((screenInfo.imageByteOrder == LSBFirst) ? + BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | + + ((screenInfo.bitmapBitOrder == LSBFirst) ? + BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + + + nxagentOrigFontNameLen = (c -> origFontNameLen < 256) ? c -> origFontNameLen : 255; + + memcpy(nxagentOrigFontName, c -> origFontName, nxagentOrigFontNameLen); + + nxagentOrigFontName[nxagentOrigFontNameLen] = 0; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + + /* NXAGENT uses useless screen pointer to pass the original font name + * to realizeFont, could be a source of problems in the future. + */ + + if (!(*pScr->RealizeFont) ((ScreenPtr)nxagentOrigFontName, pfont)) + { + CloseFont (pfont, (Font) 0); + err=BadFontName; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if( nxagentFontPriv(pfont) -> mirrorID == 0 ) + { + extern RESTYPE RT_NX_FONT; + + nxagentFontPriv(pfont) -> mirrorID = FakeClientID(0); + if (!AddResource(nxagentFontPriv(pfont) -> mirrorID, RT_NX_FONT, (pointer) pfont)) { + FreeResource(c->fontid, RT_NONE); + err = AllocError; + goto bail; + } + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/* + * Decrement font's ref count, and free storage if ref count equals zero + */ +/*ARGSUSED*/ +int +CloseFont(value, fid) + pointer value; /* must conform to DeleteType */ + XID fid; +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef LBX + LbxFreeFontTag(pfont); +#endif +#ifdef XF86BIGFONT + { + extern void XF86BigfontFreeFontShm(FontPtr); + XF86BigfontFreeFontShm(pfont); + } +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + + /* + * \ Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. \ + */ + +void +QueryFont(pFont, pReply, nProtoCCIStructs) + FontPtr pFont; + xQueryFontReply *pReply; /* caller must allocate this storage */ + int nProtoCCIStructs; +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + unsigned char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, + TwoD16Bit, &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +#if NeedFunctionPrototypes +doListFontsAndAliases(ClientPtr client, LFclosurePtr c) +#else +doListFontsAndAliases(client, c) + ClientPtr client; + LFclosurePtr c; +#endif +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount = 0; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + memmove(resolved, tmpname, resolvedlen + 1); + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + { + /* dirty hack: don't list to client fonts not existing on the remote side */ + char tmp[256]; + + memcpy(tmp, names->names[i], names->length[i]); + tmp[ names->length[i] ] = 0; + + if (nxagentFontLookUp(tmp) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases:\n"); + fprintf(stderr, " removing font: %s \n", tmp); +#endif + reply.nFonts--; + stringLens -= names->length[i]; + continue; + } + } + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + if (resolved) xfree(resolved); + return TRUE; +} + +int +ListFonts(client, pattern, length, max_names) + ClientPtr client; + unsigned char *pattern; + unsigned int length; + unsigned int max_names; +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(client, c) + ClientPtr client; + LFWIclosurePtr c; +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount = 0; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsWithInfo, + c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + c->savedName = (char *) pFontInfo; + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + + if (nxagentFontLookUp(name) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases (with info):\n"); + fprintf(stderr, " removing font: %s \n", name); +#endif + continue; + } + + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(client, length, pattern, max_names) + ClientPtr client; + int length; + unsigned char *pattern; + int max_names; +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(client, c) + ClientPtr client; + register PTclosurePtr c; +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; + FontPathElementPtr fpe; + GC *origGC = NULL; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; + else + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doPolyText, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolyText (1): client [%lx] sleeping.\n", client); +#endif + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { +#ifdef PANORAMIX + if (noPanoramiXExtension || !c->pGC->pScreen->myNum) +#endif + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolytext: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(client, pDraw, pGC, pElt, endReq, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + unsigned char *pElt; + unsigned char *endReq; + int xorg; + int yorg; + int reqType; + XID did; +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(client, c) + ClientPtr client; + register ITclosurePtr c; +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText (1): client [%lx] sleeping.\n", client); +#endif + + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(client, pDraw, pGC, nChars, data, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + int nChars; + unsigned char *data; + int xorg; + int yorg; + int reqType; + XID did; +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +#if NeedFunctionPrototypes +DetermineFPEType(char *pathname) +#else +DetermineFPEType(pathname) + char *pathname; +#endif +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +#if NeedFunctionPrototypes +FreeFontPath(FontPathElementPtr *list, int n, Bool force) +#else +FreeFontPath(list, n, force) + FontPathElementPtr *list; + Bool force; + int n; +#endif +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +#if NeedFunctionPrototypes +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) +#else +find_existing_fpe(list, num, name, len) + FontPathElementPtr *list; + int num; + unsigned char *name; + int len; +#endif +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +#if NeedFunctionPrototypes +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) +#else +SetFontPathElements(npaths, paths, bad, persist) + int npaths; + unsigned char *paths; + int *bad; + Bool persist; +#endif +{ + int i, err = 0; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe = NULL, *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) + { + len = (unsigned int) (*cp++); + + if (len == 0) + { + if (persist) + ErrorF ("Removing empty element from the valid list of fontpaths\n"); + err = BadValue; + } + else + { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) + { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) + { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + } + else + fpe = 0; + } + /* if error or can't do it, act like it's a new one */ + if (!fpe) + { + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) + { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) + { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err = BadValue; + else + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) + { + if (persist) + { + ErrorF("Could not init font path element %s, removing from list!\n", + fpe->name); + } + xfree (fpe->name); + xfree (fpe); + } + } + } + if (err != Successful) + { + if (!persist) + goto bail; + } + else + { + fplist[valid_paths++] = fpe; + } + cp += len; + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--valid_paths >= 0) + FreeFPE(fplist[valid_paths]); + xfree(fplist); + return FontToXError(err); +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(client, npaths, paths, error) + ClientPtr client; + int npaths; + unsigned char *paths; + int *error; +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadValue; + } else { + err = SetFontPathElements(npaths, paths, error, FALSE); + } + return err; +} + +int +SetDefaultFontPath(path) + char *path; +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ +#ifdef NX_TRANS_SOCKET + len = strlen(_NXGetFontPath(path)) + 1; +#else + len = strlen(path) + 1; +#endif + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; +#ifdef NX_TRANS_SOCKET + pp = (unsigned char *) _NXGetFontPath(path); +#else + pp = (unsigned char *) path; +#endif + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad, TRUE); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(count, length) + int *count; + int *length; +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +int +LoadGlyphs(client, pfont, nchars, item_size, data) + ClientPtr client; + FontPtr pfont; + unsigned nchars; + int item_size; + unsigned char *data; +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(client) + ClientPtr client; +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + +#ifndef KDRIVESERVER + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else +#endif + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); +#ifndef NOFONTSERVERACCESS + fs_register_fpe_functions(); +#endif + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (num) + int *num; +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(id) + XID id; +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(pfont, id) + FontPtr pfont; + Font id; +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(id) + Font id; +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(client) + ClientPtr client; +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(fpe, block_handler) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(fpe, block_handler, all) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; + Bool all; +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +dump_char_ascii(cip) + CharInfoPtr cip; +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif + + +typedef struct +{ + LFclosurePtr c; + OFclosurePtr oc; +} nxFs,*nxFsPtr; + +static Bool +#if NeedFunctionPrototypes +nxdoListFontsAndAliases(ClientPtr client, nxFsPtr fss) +#else +nxdoListFontsAndAliases(client, fss) + ClientPtr client; + nxFsPtr fss; +#endif +{ + LFclosurePtr c=fss->c; + OFclosurePtr oc=fss->oc; + FontPathElementPtr fpe; + int err = Successful; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int i; + int aliascount = 0; + char tmp[256]; + tmp[0]=0; + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + { + memmove(resolved, tmpname, resolvedlen); + resolved[resolvedlen] = '\0'; + } + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + { + memcpy(tmp,c->savedName,c->savedNameLen>255?255:c->savedNameLen); + tmp[c->savedNameLen>255?256:c->savedNameLen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + else + { + memcpy(tmp,name,namelen>255?255:namelen); + tmp[namelen>255?256:namelen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + { + memmove(c->savedName, name, namelen); + c->savedName[namelen] = '\0'; + } + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ +bail: +finish: + if (strlen(tmp)) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (0) font to %s\n",tmp); +#endif + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + + } + else + { + for (i = 0; i < c->names->nnames; i++) + { + if (c->names->length[i] > 255) + continue; + else + { + memcpy(tmp, c->names->names[i], c->names->length[i]); + tmp[ c->names->length[i] ] = 0; + if (nxagentFontLookUp(tmp) == 0) + continue; + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (1) font to %s\n",tmp); +#endif + break; + } + } + } + + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(c->names); + xfree(c); + xfree(fss); + if (resolved) xfree(resolved); + + return doOpenFont(client, oc); +} + +int +nxOpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + nxFsPtr fss; + LFclosurePtr c; + OFclosurePtr oc; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + if (!(fss = (nxFsPtr) xalloc(sizeof(nxFs)))) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + { + xfree(fss); + return BadAlloc; + } + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + xfree(fss); + return BadAlloc; + } + c->names = MakeFontNamesRecord(100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove( c->current.pattern, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = lenfname; + c->current.current_fpe = 0; + c->current.max_names = nxagentMaxFontNames; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + + oc = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!oc) + { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + oc->fontname = (char *) xalloc(256);/* I don't want to deal with future reallocs errors */ + oc->origFontName = pfontname; + oc->origFontNameLen = lenfname; + if (!oc->fontname) { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(oc); + xfree(fss); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + oc->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!oc->fpe_list) { + xfree(oc->fontname); + xfree(oc); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove(oc->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + oc->fpe_list[i] = font_path_elements[i]; + UseFPE(oc->fpe_list[i]); + } + oc->client = client; + oc->fontid = fid; + oc->current_fpe = 0; + oc->num_fpes = num_fpes; + oc->fnamelen = lenfname; + oc->slept = FALSE; + oc->flags = flags; + oc->non_cachable_font = cached; + fss->c=c; + fss->oc=oc; + nxdoListFontsAndAliases(client, fss); + return Success; +} + + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.NX.original new file mode 100644 index 000000000..83103ffd6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.NX.original @@ -0,0 +1,2883 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXdixfonts.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.27 2003/02/15 03:47:05 dawes Exp $ */ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */ + +#define NEED_REPLIES +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +/* +#define NXAGENT_DEBUG +*/ + +#ifdef DEBUG +#include +#endif + +#include "Agent.h" +#include "Font.h" + +#ifndef NX_TRANS_SOCKET + +#define NX_TRANS_SOCKET + +#endif + +#ifdef NX_TRANS_SOCKET + +char _NXFontPath[1024]; + +/* + * Override the default font path and make + * it configurable at run time, based on + * the NX_FONT environment. + */ + +static const char *_NXGetFontPath(const char *path) +{ + const char *fontEnv; + + /* + * Check the environment only once. + */ + + if (*_NXFontPath != '\0') + { + return _NXFontPath; + } + + fontEnv = getenv("NX_FONT"); + + if (fontEnv != NULL && *fontEnv != '\0') + { + if (strlen(fontEnv) + 1 > 1024) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n"); +#endif + goto _NXGetFontPathError; + } + + strcpy(_NXFontPath, fontEnv); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; + } + +_NXGetFontPathError: + + strcpy(_NXFontPath, path); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; +} + +#endif + +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif + +#ifdef LBX +#include "lbxserve.h" +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include "xf86bigfont.h" +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + return BadName; + case BadFontPath: + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(defaultfontname) + char *defaultfontname; +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +/* ARGSUSED */ +void +FontWakeup(data, count, LastSelectMask) + pointer data; + int count; + pointer LastSelectMask; +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +#if NeedFunctionPrototypes +UseFPE(FontPathElementPtr fpe) +#else +UseFPE(fpe) + FontPathElementPtr fpe; +#endif +{ + fpe->refcount++; +} + +static void +#if NeedFunctionPrototypes +FreeFPE (FontPathElementPtr fpe) +#else +FreeFPE (fpe) + FontPathElementPtr fpe; +#endif +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +#if NeedFunctionPrototypes +doOpenFont(ClientPtr client, OFclosurePtr c) +#else +doOpenFont(client, c) + ClientPtr client; + OFclosurePtr c; +#endif +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe = NULL; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + char nxagentOrigFontName[256]; + int nxagentOrigFontNameLen; + + /* + * Decide at runtime what FontFormat to use. + */ + Mask FontFormat = + + ((screenInfo.imageByteOrder == LSBFirst) ? + BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | + + ((screenInfo.bitmapBitOrder == LSBFirst) ? + BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + + + nxagentOrigFontNameLen = (c -> origFontNameLen < 256) ? c -> origFontNameLen : 255; + + memcpy(nxagentOrigFontName, c -> origFontName, nxagentOrigFontNameLen); + + nxagentOrigFontName[nxagentOrigFontNameLen] = 0; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + + /* NXAGENT uses useless screen pointer to pass the original font name + * to realizeFont, could be a source of problems in the future. + */ + + if (!(*pScr->RealizeFont) ((ScreenPtr)nxagentOrigFontName, pfont)) + { + CloseFont (pfont, (Font) 0); + err=BadFontName; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if( nxagentFontPriv(pfont) -> mirrorID == 0 ) + { + extern RESTYPE RT_NX_FONT; + + nxagentFontPriv(pfont) -> mirrorID = FakeClientID(0); + if (!AddResource(nxagentFontPriv(pfont) -> mirrorID, RT_NX_FONT, (pointer) pfont)) { + FreeResource(c->fontid, RT_NONE); + err = AllocError; + goto bail; + } + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/* + * Decrement font's ref count, and free storage if ref count equals zero + */ +/*ARGSUSED*/ +int +CloseFont(value, fid) + pointer value; /* must conform to DeleteType */ + XID fid; +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef LBX + LbxFreeFontTag(pfont); +#endif +#ifdef XF86BIGFONT + { + extern void XF86BigfontFreeFontShm(FontPtr); + XF86BigfontFreeFontShm(pfont); + } +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + + /* + * \ Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. \ + */ + +void +QueryFont(pFont, pReply, nProtoCCIStructs) + FontPtr pFont; + xQueryFontReply *pReply; /* caller must allocate this storage */ + int nProtoCCIStructs; +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + unsigned char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, + TwoD16Bit, &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +#if NeedFunctionPrototypes +doListFontsAndAliases(ClientPtr client, LFclosurePtr c) +#else +doListFontsAndAliases(client, c) + ClientPtr client; + LFclosurePtr c; +#endif +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount = 0; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + memmove(resolved, tmpname, resolvedlen + 1); + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + { + /* dirty hack: don't list to client fonts not existing on the remote side */ + char tmp[256]; + + memcpy(tmp, names->names[i], names->length[i]); + tmp[ names->length[i] ] = 0; + + if (nxagentFontLookUp(tmp) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases:\n"); + fprintf(stderr, " removing font: %s \n", tmp); +#endif + reply.nFonts--; + stringLens -= names->length[i]; + continue; + } + } + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + if (resolved) xfree(resolved); + return TRUE; +} + +int +ListFonts(client, pattern, length, max_names) + ClientPtr client; + unsigned char *pattern; + unsigned int length; + unsigned int max_names; +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(client, c) + ClientPtr client; + LFWIclosurePtr c; +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount = 0; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsWithInfo, + c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + c->savedName = (char *) pFontInfo; + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + + if (nxagentFontLookUp(name) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases (with info):\n"); + fprintf(stderr, " removing font: %s \n", name); +#endif + continue; + } + + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(client, length, pattern, max_names) + ClientPtr client; + int length; + unsigned char *pattern; + int max_names; +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(client, c) + ClientPtr client; + register PTclosurePtr c; +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; + FontPathElementPtr fpe; + GC *origGC = NULL; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; + else + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doPolyText, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolyText (1): client [%lx] sleeping.\n", client); +#endif + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { +#ifdef PANORAMIX + if (noPanoramiXExtension || !c->pGC->pScreen->myNum) +#endif + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolytext: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(client, pDraw, pGC, pElt, endReq, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + unsigned char *pElt; + unsigned char *endReq; + int xorg; + int yorg; + int reqType; + XID did; +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(client, c) + ClientPtr client; + register ITclosurePtr c; +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText (1): client [%lx] sleeping.\n", client); +#endif + + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(client, pDraw, pGC, nChars, data, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + int nChars; + unsigned char *data; + int xorg; + int yorg; + int reqType; + XID did; +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +#if NeedFunctionPrototypes +DetermineFPEType(char *pathname) +#else +DetermineFPEType(pathname) + char *pathname; +#endif +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +#if NeedFunctionPrototypes +FreeFontPath(FontPathElementPtr *list, int n, Bool force) +#else +FreeFontPath(list, n, force) + FontPathElementPtr *list; + Bool force; + int n; +#endif +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +#if NeedFunctionPrototypes +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) +#else +find_existing_fpe(list, num, name, len) + FontPathElementPtr *list; + int num; + unsigned char *name; + int len; +#endif +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +#if NeedFunctionPrototypes +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) +#else +SetFontPathElements(npaths, paths, bad, persist) + int npaths; + unsigned char *paths; + int *bad; + Bool persist; +#endif +{ + int i, err = 0; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe = NULL, *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) + { + len = (unsigned int) (*cp++); + + if (len == 0) + { + if (persist) + ErrorF ("Removing empty element from the valid list of fontpaths\n"); + err = BadValue; + } + else + { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) + { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) + { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + } + else + fpe = 0; + } + /* if error or can't do it, act like it's a new one */ + if (!fpe) + { + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) + { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) + { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err = BadValue; + else + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) + { + if (persist) + { + ErrorF("Could not init font path element %s, removing from list!\n", + fpe->name); + } + xfree (fpe->name); + xfree (fpe); + } + } + } + if (err != Successful) + { + if (!persist) + goto bail; + } + else + { + fplist[valid_paths++] = fpe; + } + cp += len; + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--valid_paths >= 0) + FreeFPE(fplist[valid_paths]); + xfree(fplist); + return FontToXError(err); +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(client, npaths, paths, error) + ClientPtr client; + int npaths; + unsigned char *paths; + int *error; +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadValue; + } else { + err = SetFontPathElements(npaths, paths, error, FALSE); + } + return err; +} + +int +SetDefaultFontPath(path) + char *path; +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ +#ifdef NX_TRANS_SOCKET + len = strlen(_NXGetFontPath(path)) + 1; +#else + len = strlen(path) + 1; +#endif + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; +#ifdef NX_TRANS_SOCKET + pp = (unsigned char *) _NXGetFontPath(path); +#else + pp = (unsigned char *) path; +#endif + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad, TRUE); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(count, length) + int *count; + int *length; +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +int +LoadGlyphs(client, pfont, nchars, item_size, data) + ClientPtr client; + FontPtr pfont; + unsigned nchars; + int item_size; + unsigned char *data; +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(client) + ClientPtr client; +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + +#ifndef KDRIVESERVER + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else +#endif + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); +#ifndef NOFONTSERVERACCESS + fs_register_fpe_functions(); +#endif + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (num) + int *num; +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(id) + XID id; +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(pfont, id) + FontPtr pfont; + Font id; +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(id) + Font id; +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(client) + ClientPtr client; +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(fpe, block_handler) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(fpe, block_handler, all) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; + Bool all; +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +dump_char_ascii(cip) + CharInfoPtr cip; +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif + + +typedef struct +{ + LFclosurePtr c; + OFclosurePtr oc; +} nxFs,*nxFsPtr; + +static Bool +#if NeedFunctionPrototypes +nxdoListFontsAndAliases(ClientPtr client, nxFsPtr fss) +#else +nxdoListFontsAndAliases(client, fss) + ClientPtr client; + nxFsPtr fss; +#endif +{ + LFclosurePtr c=fss->c; + OFclosurePtr oc=fss->oc; + FontPathElementPtr fpe; + int err = Successful; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int i; + int aliascount = 0; + char tmp[256]; + tmp[0]=0; + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + { + memmove(resolved, tmpname, resolvedlen); + resolved[resolvedlen] = '\0'; + } + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + { + memcpy(tmp,c->savedName,c->savedNameLen>255?255:c->savedNameLen); + tmp[c->savedNameLen>255?256:c->savedNameLen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + else + { + memcpy(tmp,name,namelen>255?255:namelen); + tmp[namelen>255?256:namelen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + { + memmove(c->savedName, name, namelen); + c->savedName[namelen] = '\0'; + } + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ +bail: +finish: + if (strlen(tmp)) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (0) font to %s\n",tmp); +#endif + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + + } + else + { + for (i = 0; i < c->names->nnames; i++) + { + if (c->names->length[i] > 255) + continue; + else + { + memcpy(tmp, c->names->names[i], c->names->length[i]); + tmp[ c->names->length[i] ] = 0; + if (nxagentFontLookUp(tmp) == 0) + continue; + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (1) font to %s\n",tmp); +#endif + break; + } + } + } + + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(c->names); + xfree(c); + xfree(fss); + if (resolved) xfree(resolved); + + return doOpenFont(client, oc); +} + +int +nxOpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + nxFsPtr fss; + LFclosurePtr c; + OFclosurePtr oc; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + if (!(fss = (nxFsPtr) xalloc(sizeof(nxFs)))) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + { + xfree(fss); + return BadAlloc; + } + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + xfree(fss); + return BadAlloc; + } + c->names = MakeFontNamesRecord(100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove( c->current.pattern, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = lenfname; + c->current.current_fpe = 0; + c->current.max_names = nxagentMaxFontNames; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + + oc = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!oc) + { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + oc->fontname = (char *) xalloc(256);/* I don't want to deal with future reallocs errors */ + oc->origFontName = pfontname; + oc->origFontNameLen = lenfname; + if (!oc->fontname) { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(oc); + xfree(fss); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + oc->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!oc->fpe_list) { + xfree(oc->fontname); + xfree(oc); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove(oc->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + oc->fpe_list[i] = font_path_elements[i]; + UseFPE(oc->fpe_list[i]); + } + oc->client = client; + oc->fontid = fid; + oc->current_fpe = 0; + oc->num_fpes = num_fpes; + oc->fnamelen = lenfname; + oc->slept = FALSE; + oc->flags = flags; + oc->non_cachable_font = cached; + fss->c=c; + fss->oc=oc; + nxdoListFontsAndAliases(client, fss); + return Success; +} + + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.XF86.original new file mode 100644 index 000000000..5386c908b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.XF86.original @@ -0,0 +1,2223 @@ +/* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.27 2003/02/15 03:47:05 dawes Exp $ */ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */ + +#define NEED_REPLIES +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +#ifdef DEBUG +#include +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#endif + +#ifdef LBX +#include "lbxserve.h" +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include "xf86bigfont.h" +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + return BadName; + case BadFontPath: + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(defaultfontname) + char *defaultfontname; +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(fpe) + FontPathElementPtr fpe; +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +/* ARGSUSED */ +void +FontWakeup(data, count, LastSelectMask) + pointer data; + int count; + pointer LastSelectMask; +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +#if NeedFunctionPrototypes +UseFPE(FontPathElementPtr fpe) +#else +UseFPE(fpe) + FontPathElementPtr fpe; +#endif +{ + fpe->refcount++; +} + +static void +#if NeedFunctionPrototypes +FreeFPE (FontPathElementPtr fpe) +#else +FreeFPE (fpe) + FontPathElementPtr fpe; +#endif +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +#if NeedFunctionPrototypes +doOpenFont(ClientPtr client, OFclosurePtr c) +#else +doOpenFont(client, c) + ClientPtr client; + OFclosurePtr c; +#endif +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe = NULL; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + /* + * Decide at runtime what FontFormat to use. + */ + Mask FontFormat = + + ((screenInfo.imageByteOrder == LSBFirst) ? + BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | + + ((screenInfo.bitmapBitOrder == LSBFirst) ? + BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + if (!(*pScr->RealizeFont) (pScr, pfont)) + { + CloseFont (pfont, (Font) 0); + err = AllocError; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + ClientWakeup(c->client); + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/* + * Decrement font's ref count, and free storage if ref count equals zero + */ +/*ARGSUSED*/ +int +CloseFont(value, fid) + pointer value; /* must conform to DeleteType */ + XID fid; +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef LBX + LbxFreeFontTag(pfont); +#endif +#ifdef XF86BIGFONT + XF86BigfontFreeFontShm(pfont); +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + + /* + * \ Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. \ + */ + +void +QueryFont(pFont, pReply, nProtoCCIStructs) + FontPtr pFont; + xQueryFontReply *pReply; /* caller must allocate this storage */ + int nProtoCCIStructs; +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + unsigned char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, + TwoD16Bit, &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +#if NeedFunctionPrototypes +doListFontsAndAliases(ClientPtr client, LFclosurePtr c) +#else +doListFontsAndAliases(client, c) + ClientPtr client; + LFclosurePtr c; +#endif +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount = 0; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + memmove(resolved, tmpname, resolvedlen + 1); + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + if (resolved) xfree(resolved); + return TRUE; +} + +int +ListFonts(client, pattern, length, max_names) + ClientPtr client; + unsigned char *pattern; + unsigned int length; + unsigned int max_names; +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(client, c) + ClientPtr client; + LFWIclosurePtr c; +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount = 0; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsWithInfo, + c); + c->slept = TRUE; + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + c->savedName = (char *) pFontInfo; + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(client, length, pattern, max_names) + ClientPtr client; + int length; + unsigned char *pattern; + int max_names; +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(client, c) + ClientPtr client; + register PTclosurePtr c; +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; + FontPathElementPtr fpe; + GC *origGC = NULL; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; + else + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doPolyText, + (pointer) c); + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { +#ifdef PANORAMIX + if (noPanoramiXExtension || !c->pGC->pScreen->myNum) +#endif + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(client, pDraw, pGC, pElt, endReq, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + unsigned char *pElt; + unsigned char *endReq; + int xorg; + int yorg; + int reqType; + XID did; +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(client, c) + ClientPtr client; + register ITclosurePtr c; +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(client, pDraw, pGC, nChars, data, xorg, yorg, reqType, did) + ClientPtr client; + DrawablePtr pDraw; + GC *pGC; + int nChars; + unsigned char *data; + int xorg; + int yorg; + int reqType; + XID did; +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +#if NeedFunctionPrototypes +DetermineFPEType(char *pathname) +#else +DetermineFPEType(pathname) + char *pathname; +#endif +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +#if NeedFunctionPrototypes +FreeFontPath(FontPathElementPtr *list, int n, Bool force) +#else +FreeFontPath(list, n, force) + FontPathElementPtr *list; + Bool force; + int n; +#endif +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +#if NeedFunctionPrototypes +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) +#else +find_existing_fpe(list, num, name, len) + FontPathElementPtr *list; + int num; + unsigned char *name; + int len; +#endif +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +#if NeedFunctionPrototypes +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) +#else +SetFontPathElements(npaths, paths, bad, persist) + int npaths; + unsigned char *paths; + int *bad; + Bool persist; +#endif +{ + int i, err = 0; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe = NULL, *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) + { + len = (unsigned int) (*cp++); + + if (len == 0) + { + if (persist) + ErrorF ("Removing empty element from the valid list of fontpaths\n"); + err = BadValue; + } + else + { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) + { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) + { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + } + else + fpe = 0; + } + /* if error or can't do it, act like it's a new one */ + if (!fpe) + { + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) + { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) + { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err = BadValue; + else + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) + { + if (persist) + { + ErrorF("Could not init font path element %s, removing from list!\n", + fpe->name); + } + xfree (fpe->name); + xfree (fpe); + } + } + } + if (err != Successful) + { + if (!persist) + goto bail; + } + else + { + fplist[valid_paths++] = fpe; + } + cp += len; + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--valid_paths >= 0) + FreeFPE(fplist[valid_paths]); + xfree(fplist); + return FontToXError(err); +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(client, npaths, paths, error) + ClientPtr client; + int npaths; + unsigned char *paths; + int *error; +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadValue; + } else { + err = SetFontPathElements(npaths, paths, error, FALSE); + } + return err; +} + +int +SetDefaultFontPath(path) + char *path; +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ + len = strlen(path) + 1; + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; + pp = (unsigned char *) path; + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad, TRUE); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(count, length) + int *count; + int *length; +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +int +LoadGlyphs(client, pfont, nchars, item_size, data) + ClientPtr client; + FontPtr pfont; + unsigned nchars; + int item_size; + unsigned char *data; +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(client) + ClientPtr client; +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + +#ifndef KDRIVESERVER + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else +#endif + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); +#ifndef NOFONTSERVERACCESS + fs_register_fpe_functions(); +#endif + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (num) + int *num; +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(id) + XID id; +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(pfont, id) + FontPtr pfont; + Font id; +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(id) + Font id; +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(client) + ClientPtr client; +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(fpe, block_handler) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(fpe, block_handler, all) + FontPathElementPtr fpe; + BlockHandlerProcPtr block_handler; + Bool all; +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +dump_char_ascii(cip) + CharInfoPtr cip; +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXevents.c b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c new file mode 100644 index 000000000..dd607e0ca --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c @@ -0,0 +1,4797 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXevents.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/events.c,v 3.46 2002/09/17 01:15:09 dawes Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) 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. * +* * +*****************************************************************/ + +/* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "Xlib.h" +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "globals.h" + +#ifdef XKB +#include "XKBsrv.h" +#if NeedFunctionPrototypes +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +#else +extern Bool XkbFilterEvents(); +#endif +#endif + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif + +#include "XIproto.h" +#include "exevents.h" +#include "extnsionst.h" + +#include "dixevents.h" +#include "dixgrabs.h" +#include "../../dix/dispatch.h" + +#include "NXlib.h" + +#include "Events.h" +#include "Windows.h" + +extern Display *nxagentDisplay; + +extern WindowPtr nxagentLastEnteredWindow; + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the ButtonMotionMasks are equal + * to the corresponding ButtonMasks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define XE_KBPTR (xE->u.keyButtonPointer) + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +CallbackListPtr EventCallback; +CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +typedef struct { + int x, y; + ScreenPtr pScreen; +} HotSpot; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif +} sprite; /* info about the cursor sprite */ + +static void DoEnterLeaveEvents( +#if NeedFunctionPrototypes + WindowPtr /*fromWin*/, + WindowPtr /*toWin*/, + int /*mode*/ +#endif +); + +static WindowPtr XYToWindow( +#if NeedFunctionPrototypes + int /*x*/, + int /*y*/ +#endif +); + +extern int lastEvent; + +static Mask lastEventMask; + +#ifdef XINPUT +extern int DeviceMotionNotify; +#endif + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x7c /* key and button events */ +}; + +#ifdef PANORAMIX + +static void ConfineToShape(RegionPtr shape, int *px, int *py); +static void SyntheticMotion(int x, int y); +static void PostNewCursor(void); + +static Bool +XineramaSetCursorPosition( + int x, + int y, + Bool generateEvent +){ + ScreenPtr pScreen; + BoxRec box; + int i; + + /* x,y are in Screen 0 coordinates. We need to decide what Screen + to send the message too and what the coordinates relative to + that screen are. */ + + pScreen = sprite.screen; + x += panoramiXdataPtr[0].x; + y += panoramiXdataPtr[0].y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) + { + FOR_NSCREENS(i) + { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) + { + pScreen = screenInfo.screens[i]; + break; + } + } + } + + sprite.screen = pScreen; + sprite.hotPhys.x = x - panoramiXdataPtr[0].x; + sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + x -= panoramiXdataPtr[pScreen->myNum].x; + y -= panoramiXdataPtr[pScreen->myNum].y; + + return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); +} + + +static void +XineramaConstrainCursor(void) +{ + ScreenPtr pScreen = sprite.screen; + BoxRec newBox = sprite.physLimits; + + /* Translate the constraining box to the screen + the sprite is actually on */ + newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + + (* pScreen->ConstrainCursor)(pScreen, &newBox); +} + +static void +XineramaCheckPhysLimits( + CursorPtr cursor, + Bool generateEvents +){ + HotSpot new; + + if (!cursor) + return; + + new = sprite.hotPhys; + + /* I don't care what the DDX has to say about it */ + sprite.physLimits = sprite.hotLimits; + + /* constrain the pointer to those limits */ + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) /* more work if the shape is a mess */ + ConfineToShape(sprite.hotShape, &new.x, &new.y); + + if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + XineramaSetCursorPosition (new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } + + /* Tell DDX what the limits are */ + XineramaConstrainCursor(); +} + + +static Bool +XineramaSetWindowPntrs(WindowPtr pWin) +{ + if(pWin == WindowTable[0]) { + memcpy(sprite.windows, WindowTable, + PanoramiXNumScreens*sizeof(WindowPtr)); + } else { + PanoramiXRes *win; + int i; + + win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); + + if(!win) + return FALSE; + + for(i = 0; i < PanoramiXNumScreens; i++) { + sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!sprite.windows[i]) /* window is being unmapped */ + return FALSE; + } + } + return TRUE; +} + +static void +XineramaCheckVirtualMotion( + QdEventPtr qe, + WindowPtr pWin +){ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + int x, y, off_x, off_y, i; + BoxRec lims; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg2, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; + + if (REGION_NUM_RECTS(&sprite.Reg2) > 1) + ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +} + + +static Bool +XineramaCheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + /* Motion events entering DIX get translated to Screen 0 + coordinates. Replayed events have already been + translated since they've entered DIX before */ + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + XineramaSetCursorPosition( + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + + +static void +XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +{ + + if (syncEvents.playingEvents) + { + XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + int x, y, off_x, off_y, i; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg1, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + + if(REGION_NUM_RECTS(&sprite.Reg1) > 1) + sprite.hotShape = &sprite.Reg1; + else + sprite.hotShape = NullRegion; + + sprite.confined = FALSE; + sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + + XineramaCheckPhysLimits(sprite.current, generateEvents); + } +} + + +static void +XineramaChangeToCursor(CursorPtr cursor) +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(cursor, FALSE); + (*sprite.screen->DisplayCursor)(sprite.screen, cursor); + sprite.current = cursor; + } +} + + +#endif /* PANORAMIX */ + +void +SetMaskForEvent(mask, event) + Mask mask; + int event; +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +void +SetCriticalEvent(event) + int event; +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +#if NeedFunctionPrototypes +SyntheticMotion(int x, int y) +#else +SyntheticMotion(x, y) + int x, y; +#endif +{ + xEvent xE; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x; + y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +#if NeedFunctionPrototypes +ConfineToShape(RegionPtr shape, int *px, int *py) +#else +ConfineToShape(shape, px, py) + RegionPtr shape; + int *px, *py; +#endif +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +#if NeedFunctionPrototypes +CheckPhysLimits( + CursorPtr cursor, + Bool generateEvents, + Bool confineToScreen, + ScreenPtr pScreen) +#else +CheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen) + CursorPtr cursor; + Bool generateEvents; + Bool confineToScreen; + ScreenPtr pScreen; +#endif +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +#if NeedFunctionPrototypes +CheckVirtualMotion( + register QdEventPtr qe, + register WindowPtr pWin) +#else +CheckVirtualMotion(qe, pWin) + register QdEventPtr qe; + register WindowPtr pWin; +#endif +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaCheckVirtualMotion(qe, pWin); + return; + } +#endif + if (qe) + { + sprite.hot.pScreen = qe->pScreen; + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaConfineCursorToWindow(pWin, generateEvents); + return; + } +#endif + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +#if NeedFunctionPrototypes +ChangeToCursor(CursorPtr cursor) +#else +ChangeToCursor(cursor) + CursorPtr cursor; +#endif +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaChangeToCursor(cursor); + return; + } +#endif + + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, sprite.confined, + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + sprite.current = cursor; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(a, b) + register WindowPtr a, b; +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +#if NeedFunctionPrototypes +PostNewCursor(void) +#else +PostNewCursor() +#endif +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +void +GetSpritePosition(px, py) + int *px, *py; +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#ifdef PANORAMIX +int +XineramaGetCursorScreen() +{ + if(!noPanoramiXExtension) { + return sprite.screen->myNum; + } else { + return 0; + } +} +#endif /* PANORAMIX */ + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +#if NeedFunctionPrototypes +MonthChangedOrBadTime(register xEvent *xE) +#else +MonthChangedOrBadTime(xE) + register xEvent *xE; +#endif +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) + currentTime.months++; + else + XE_KBPTR.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(xE) + register xEvent *xE; +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xE, device, count) + xEvent *xE; + DeviceIntPtr device; + int count; +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + } +#endif + sprite.hotPhys.x = XE_KBPTR.rootX; + sprite.hotPhys.y = XE_KBPTR.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = XE_KBPTR.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +#if NeedFunctionPrototypes +PlayReleasedEvents(void) +#else +PlayReleasedEvents() +#endif +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +#if NeedFunctionPrototypes +FreezeThaw(register DeviceIntPtr dev, Bool frozen) +#else +FreezeThaw(dev, frozen) + register DeviceIntPtr dev; + Bool frozen; +#endif +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + + w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < spriteTraceGood; i++) + { + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + } + goto playmore; + } + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +#ifdef RANDR +void +ScreenRestructured (ScreenPtr pScreen) +{ + GrabPtr grab; + + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +CheckGrabForSyncs(thisDev, thisMode, otherMode) + register DeviceIntPtr thisDev; + Bool thisMode, otherMode; +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(mouse, grab, time, autoGrab) + register GrabPtr grab; + register DeviceIntPtr mouse; + TimeStamp time; + Bool autoGrab; +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + + #ifdef NXAGENT_SERVER + + /* + * If grab is synchronous, events are delivered to clients only if they send + * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the + * delivered event is saved in a queue and replayed later, when grab is released. + * We should export sync grab to X as async in order to avoid events to be + * queued twice, in the agent and in the X server. This solution have a drawback: + * replayed events are not delivered to that application that are not clients of + * the agent. + * A different solution could be to make the grab asynchronous in the agent and + * to export it as synchronous. But this seems to be less safe. + * + * To make internal grab asynchronous, change previous line as follows. + * + * if (nxagentOption(Rootless)) + * { + * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode); + * } + * else + * { + * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + * } + */ + + if (nxagentOption(Rootless) == 1) + { + /* + * FIXME: We should use the correct value + * for the cursor. Temporarily we set it + * to None. + */ + + int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, + nxagentCollectGrabPointerPredicate); + + NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window), + 1, grab -> eventMask & PointerGrabMask, + GrabModeAsync, GrabModeAsync, (grab -> confineTo) ? + nxagentWindow(grab -> confineTo) : None, + None, CurrentTime); + } + + #endif +} + +void +DeactivatePointerGrab(mouse) + register DeviceIntPtr mouse; +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); + + #ifdef NXAGENT_SERVER + + if (nxagentOption(Rootless) == 1) + { + XUngrabPointer(nxagentDisplay, CurrentTime); + + if (sprite.win == ROOT) + { + mouse -> button -> state &= + ~(Button1Mask | Button2Mask | Button3Mask | + Button4Mask | Button5Mask); + } + } + + #endif +} + +void +ActivateKeyboardGrab(keybd, grab, time, passive) + register DeviceIntPtr keybd; + GrabPtr grab; + TimeStamp time; + Bool passive; +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(keybd) + register DeviceIntPtr keybd; +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(client, time, thisDev, newState) + ClientPtr client; + TimeStamp time; + register DeviceIntPtr thisDev; + int newState; +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(client) + register ClientPtr client; +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * This is not necessary if we export grab to X as asynchronous. + * + * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard && + * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard) + * { + * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime); + * } + */ + + return Success; +} + +void +ReleaseActiveGrabs(client) + ClientPtr client; +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +int +TryClientEvents (client, pEvents, count, mask, filter, grab) + ClientPtr client; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask mask, filter; +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); + fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint + ((deviceKeyButtonPointer*)pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { +#ifdef SMART_SCHEDULE + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; +#endif + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx) + register WindowPtr pWin; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask filter; + int mskidx; +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask = 0; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) && + deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +#ifdef PANORAMIX +static int +XineramaTryClientEventsResult( + ClientPtr client, + GrabPtr grab, + Mask mask, + Mask filter +){ + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) return -1; + else return 1; + } + return 0; +} +#endif + +int +MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient) + register WindowPtr pWin; + xEvent *pEvents; + int count; + Mask filter; + ClientPtr dontClient; +{ + register OtherClients *other; + + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + wClient(pWin), NullGrab, pWin->eventMask, filter); +#endif + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + rClient(other), NullGrab, other->mask, filter); +#endif + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +#if NeedFunctionPrototypes +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +#else +FixUpEventFromWindow(xE, pWin, child, calcChild) + xEvent *xE; + WindowPtr pWin; + Window child; + Bool calcChild; +#endif +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xTrue; + XE_KBPTR.child = child; + XE_KBPTR.eventX = + XE_KBPTR.rootX - pWin->drawable.x; + XE_KBPTR.eventY = + XE_KBPTR.rootY - pWin->drawable.y; + } + else + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + } +} + +int +DeliverDeviceEvents(pWin, xE, grab, stopAt, dev, count) + register WindowPtr pWin, stopAt; + register xEvent *xE; + GrabPtr grab; + DeviceIntPtr dev; + int count; +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +int +DeliverEvents(pWin, xE, count, otherParent) + register WindowPtr pWin, otherParent; + register xEvent *xE; + int count; +{ + Mask filter; + int deliveries; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return count; +#endif + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + + +static Bool +PointInBorderSize(WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(POINT_IN_REGION(sprite.screen, + &sprite.windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + &box)) + return TRUE; + } + } +#endif + return FALSE; +} + +static WindowPtr +#if NeedFunctionPrototypes +XYToWindow(int x, int y) +#else +XYToWindow(x, y) + int x, y; +#endif +{ + register WindowPtr pWin; + + spriteTraceGood = 1; /* root window still there */ + + if (nxagentOption(Rootless)) + { + if (nxagentLastEnteredWindow == NULL) + { + return ROOT; + } + + pWin = ROOT->lastChild; + + while (pWin && pWin != ROOT->firstChild && pWin != nxagentLastEnteredWindow) + { + pWin = pWin->prevSib; + } + } + else + { + pWin = ROOT->firstChild; + } + + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +#if NeedFunctionPrototypes +CheckMotion(xEvent *xE) +#else +CheckMotion(xE) + xEvent *xE; +#endif +{ + WindowPtr prevSpriteWin = sprite.win; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaCheckMotion(xE); +#endif + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif + sprite.hotPhys = sprite.hot; + + /* + * This code force cursor position to be inside the + * root window of the agent. We can't view a reason + * to do this and it interacts in an undesirable way + * with toggling fullscreen. + * + * if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + * (sprite.hotPhys.y != XE_KBPTR.rootY)) + * { + * (*sprite.hotPhys.pScreen->SetCursorPosition)( + * sprite.hotPhys.pScreen, + * sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + * } + */ + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +void +DefineInitialRootWindow(win) + register WindowPtr win; +{ + register ScreenPtr pScreen = win->drawable.pScreen; + extern void nxagentInitViewportFrame(ScreenPtr, WindowPtr); + extern int nxagentShadowInit(ScreenPtr, WindowPtr); + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; + sprite.win = win; + sprite.current = wCursor (win); + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.confineWin = NullWindow; + sprite.screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_INIT(pScreen, &sprite.Reg1, NullBox, 1); + REGION_INIT(pScreen, &sprite.Reg2, NullBox, 1); + } +#endif + + nxagentInitViewportFrame(pScreen, win); + + if (nxagentOption(Shadow)) + { + if (nxagentShadowInit(pScreen, win) == -1) + { + GiveUp(0); + } + } +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +/*ARGSUSED*/ +void +WindowHasNewCursor(pWin) + WindowPtr pWin; +{ + PostNewCursor(); +} + +void +NewCurrentScreen(newScreen, x, y) + ScreenPtr newScreen; + int x,y; +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + panoramiXdataPtr[0].x; + sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + panoramiXdataPtr[0].y; + if (newScreen != sprite.screen) { + sprite.screen = newScreen; + /* Make sure we tell the DDX to update its copy of the screen */ + if(sprite.confineWin) + XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + else + XineramaConfineCursorToWindow(WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get + told of the pointer warp so we reposition it here */ + if(!syncEvents.playingEvents) + (*sprite.screen->SetCursorPosition)(sprite.screen, + sprite.hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x, + sprite.hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + } + } else +#endif + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +#ifdef PANORAMIX + +static Bool +XineramaPointInWindowIsVisible( + WindowPtr pWin, + int x, + int y +) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + int i, xoff, yoff; + + if (!pWin->realized) return FALSE; + + if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + if(!XineramaSetWindowPntrs(pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; + + for(i = 1; i < PanoramiXNumScreens; i++) { + pWin = sprite.windows[i]; + pScreen = pWin->drawable.pScreen; + x = xoff - panoramiXdataPtr[i].x; + y = yoff - panoramiXdataPtr[i].y; + + if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + } + + return FALSE; +} + +static int +XineramaWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + + REQUEST(xWarpPointerReq); + + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if(source == WindowTable[0]) { + winX -= panoramiXdataPtr[0].x; + winY -= panoramiXdataPtr[0].y; + } + if (x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !XineramaPointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) { + x = dest->drawable.x; + y = dest->drawable.y; + if(dest == WindowTable[0]) { + x -= panoramiXdataPtr[0].x; + y -= panoramiXdataPtr[0].y; + } + } + + x += stuff->dstX; + y += stuff->dstY; + + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + + XineramaSetCursorPosition(x, y, TRUE); + + return Success; +} + +#endif + + +int +ProcWarpPointer(client) + ClientPtr client; +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaWarpPointer(client); +#endif + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = sprite.hotPhys.pScreen; + + x += stuff->dstX; + y += stuff->dstY; + + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#if defined(SHAPE) + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + return TRUE; + } + } +#endif + return FALSE; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +#if NeedFunctionPrototypes +CheckPassiveGrabsOnWindow( + WindowPtr pWin, + register DeviceIntPtr device, + register xEvent *xE, + int count) +#else +CheckPassiveGrabsOnWindow(pWin, device, xE, count) + WindowPtr pWin; + register DeviceIntPtr device; + register xEvent *xE; + int count; +#endif +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if (device == grab->modifierDevice && + (xE->u.u.type == KeyPress +#ifdef XINPUT + || xE->u.u.type == DeviceKeyPress +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) + { +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + XE_KBPTR.state &= 0x1f00; + XE_KBPTR.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/* +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(device, xE, checkFirst, count) + register DeviceIntPtr device; + register xEvent *xE; + int checkFirst; + int count; +{ + register int i; + register WindowPtr pWin = NULL; + register FocusClassPtr focus = device->focus; + + if ((xE->u.u.type == ButtonPress +#ifdef XINPUT + || xE->u.u.type == DeviceButtonPress +#endif + ) && device->button->buttonsDown != 1) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(keybd, xE, window, count) + xEvent *xE; + DeviceIntPtr keybd; + WindowPtr window; + int count; +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(xE, thisDev, deactivateGrab, count) + register xEvent *xE; + register DeviceIntPtr thisDev; + Bool deactivateGrab; + int count; +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (xE, keybd, count) +#else +ProcessKeyboardEvent (xE, keybd, count) +#endif + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); +} + +#ifdef XKB +/* This function is used to set the key pressed or key released state - + this is only used when the pressing of keys does not cause + CoreProcessKeyEvent to be called, as in for example Mouse Keys. +*/ +void +FixKeyState (xE, keybd) + register xEvent *xE; + register DeviceIntPtr keybd; +{ + int key, bit; + register BYTE *kptr; + register KeyClassPtr keyc = keybd->key; + + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("FixKeyState: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + *kptr |= bit; + break; + case KeyRelease: + *kptr &= ~bit; + break; + default: + FatalError("Impossible keyboard event"); + } +} +#endif + +void +#ifdef XKB +CoreProcessPointerEvent (xE, mouse, count) +#else +ProcessPointerEvent (xE, mouse, count) +#endif + register xEvent *xE; + register DeviceIntPtr mouse; + int count; +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi; + + xkbi = inputInfo.keyboard->key->xkbInfo; +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + if (!(*kptr & bit)) + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (*kptr & bit) + --butc->buttonsDown; + if (!butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +int +OtherClientGone(value, id) + pointer value; /* must conform to DeleteType */ + XID id; +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(pWin, client, mask) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#ifdef SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#ifdef SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +/*ARGSUSED*/ +int +EventSuppressForWindow(pWin, client, mask, checkOptional) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; + Bool *checkOptional; +{ + register int i, free; + + if ((mask & ~PropagateMask) && !permitOldBugs) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +#if NeedFunctionPrototypes +CommonAncestor( + register WindowPtr a, + register WindowPtr b) +#else +CommonAncestor(a, b) + register WindowPtr a, b; +#endif +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +#if NeedFunctionPrototypes +EnterLeaveEvent( + int type, + int mode, + int detail, + register WindowPtr pWin, + Window child) +#else +EnterLeaveEvent(type, mode, detail, pWin, child) + int type, mode, detail; + register WindowPtr pWin; + Window child; +#endif +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XCSECURITY + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +#if NeedFunctionPrototypes +EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +#else +EnterNotifies(ancestor, child, mode, detail) + WindowPtr ancestor, child; + int mode, detail; +#endif +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +#if NeedFunctionPrototypes +LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +#else +LeaveNotifies(child, ancestor, mode, detail) + WindowPtr child, ancestor; + int detail, mode; +#endif +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +#if NeedFunctionPrototypes +DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +#else +DoEnterLeaveEvents(fromWin, toWin, mode) + WindowPtr fromWin, toWin; + int mode; +#endif +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +#if NeedFunctionPrototypes +FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin) +#else +FocusEvent(dev, type, mode, detail, pWin) + DeviceIntPtr dev; + int type, mode, detail; + register WindowPtr pWin; +#endif +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XCSECURITY + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +#if NeedFunctionPrototypes +FocusInEvents( + DeviceIntPtr dev, + WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, + int mode, int detail, + Bool doAncestor) +#else +FocusInEvents(dev, ancestor, child, skipChild, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr ancestor, child, skipChild; + int mode, detail; + Bool doAncestor; +#endif +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +#if NeedFunctionPrototypes +FocusOutEvents( + DeviceIntPtr dev, + WindowPtr child, WindowPtr ancestor, + int mode, int detail, + Bool doAncestor) +#else +FocusOutEvents(dev, child, ancestor, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr child, ancestor; + int mode; + int detail; + Bool doAncestor; +#endif +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(dev, fromWin, toWin, mode) + DeviceIntPtr dev; + WindowPtr fromWin, toWin; + int mode; +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; iparent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); + else +#endif + for (i=0; iparent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +#if NeedFunctionPrototypes +SetInputFocus( + ClientPtr client, + DeviceIntPtr dev, + Window focusID, + CARD8 revertTo, + Time ctime, + Bool followOK) +#else +SetInputFocus(client, dev, focusID, revertTo, ctime, followOK) + ClientPtr client; + DeviceIntPtr dev; + Window focusID; + CARD8 revertTo; + Time ctime; + Bool followOK; +#endif +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)(long)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(client) + ClientPtr client; +{ + xGetInputFocusReply rep; + /* REQUEST(xReq); */ + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(client) + ClientPtr client; +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(client, dev, this_mode, other_mode, grabWindow, ownerEvents, ctime, + mask, status) + register ClientPtr client; + register DeviceIntPtr dev; + unsigned this_mode; + unsigned other_mode; + Window grabWindow; + unsigned ownerEvents; + Time ctime; + Mask mask; + CARD8 *status; +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(client) + ClientPtr client; +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(client) + ClientPtr client; +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if(stuff->id == rep.root) { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +void +CloseDownEvents(void) +{ + xfree(spriteTrace); + spriteTrace = NULL; + spriteTraceSize = 0; +} + +int +ProcSendEvent(client) + ClientPtr client; +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + +#ifdef NXAGENT_CLIPBOARD + + if (stuff -> event.u.u.type == SelectionNotify) + { + extern int nxagentSendNotify(xEvent*); + if (nxagentSendNotify(&stuff->event) == 1) + return Success; + } +#endif + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32 && + !permitOldBugs) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(client) + ClientPtr client; +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(client) + ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, + NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + + +int +ProcGrabButton(client) + ClientPtr client; +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + permitOldBugs ? (Mask)(stuff->eventMask | + ButtonPressMask | ButtonReleaseMask) : + (Mask)stuff->eventMask, + (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, + (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers, + ButtonPress, stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(client) + ClientPtr client; +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(pWin, freeResources) + WindowPtr pWin; + Bool freeResources; +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/* Call this whenever some window at or below pWin has changed geometry */ + +/*ARGSUSED*/ +void +CheckCursorConfinement(pWin) + WindowPtr pWin; +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; +#endif + + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(confineTo)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(pWin, client) + WindowPtr pWin; + ClientPtr client; +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(client) + ClientPtr client; +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + Bool displayed; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; +#ifdef PANORAMIX + if(!noPanoramiXExtension) + displayed = (pscr == sprite.screen); + else +#endif + displayed = (pscr == sprite.hotPhys.pScreen); + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && displayed); + } + return (Success); +} + +void +WriteEventsToClient(pClient, count, events) + ClientPtr pClient; + int count; + xEvent *events; +{ +#ifdef PANORAMIX + xEvent eventCopy; +#endif + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + +#ifdef PANORAMIX + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + { + switch(events->u.u.type) { + case MotionNotify: + case ButtonPress: + case ButtonRelease: + case KeyPress: + case KeyRelease: + case EnterNotify: + case LeaveNotify: + /* + When multiple clients want the same event DeliverEventsToWindow + passes the same event structure multiple times so we can't + modify the one passed to us + */ + count = 1; /* should always be 1 */ + memcpy(&eventCopy, events, sizeof(xEvent)); + eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) + { + eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; + } + events = &eventCopy; + break; + default: break; + } + } +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXevents.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c.NX.original new file mode 100644 index 000000000..dd607e0ca --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c.NX.original @@ -0,0 +1,4797 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXevents.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/events.c,v 3.46 2002/09/17 01:15:09 dawes Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) 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. * +* * +*****************************************************************/ + +/* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "Xlib.h" +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "globals.h" + +#ifdef XKB +#include "XKBsrv.h" +#if NeedFunctionPrototypes +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +#else +extern Bool XkbFilterEvents(); +#endif +#endif + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif + +#include "XIproto.h" +#include "exevents.h" +#include "extnsionst.h" + +#include "dixevents.h" +#include "dixgrabs.h" +#include "../../dix/dispatch.h" + +#include "NXlib.h" + +#include "Events.h" +#include "Windows.h" + +extern Display *nxagentDisplay; + +extern WindowPtr nxagentLastEnteredWindow; + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the ButtonMotionMasks are equal + * to the corresponding ButtonMasks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define XE_KBPTR (xE->u.keyButtonPointer) + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +CallbackListPtr EventCallback; +CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +typedef struct { + int x, y; + ScreenPtr pScreen; +} HotSpot; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif +} sprite; /* info about the cursor sprite */ + +static void DoEnterLeaveEvents( +#if NeedFunctionPrototypes + WindowPtr /*fromWin*/, + WindowPtr /*toWin*/, + int /*mode*/ +#endif +); + +static WindowPtr XYToWindow( +#if NeedFunctionPrototypes + int /*x*/, + int /*y*/ +#endif +); + +extern int lastEvent; + +static Mask lastEventMask; + +#ifdef XINPUT +extern int DeviceMotionNotify; +#endif + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x7c /* key and button events */ +}; + +#ifdef PANORAMIX + +static void ConfineToShape(RegionPtr shape, int *px, int *py); +static void SyntheticMotion(int x, int y); +static void PostNewCursor(void); + +static Bool +XineramaSetCursorPosition( + int x, + int y, + Bool generateEvent +){ + ScreenPtr pScreen; + BoxRec box; + int i; + + /* x,y are in Screen 0 coordinates. We need to decide what Screen + to send the message too and what the coordinates relative to + that screen are. */ + + pScreen = sprite.screen; + x += panoramiXdataPtr[0].x; + y += panoramiXdataPtr[0].y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) + { + FOR_NSCREENS(i) + { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) + { + pScreen = screenInfo.screens[i]; + break; + } + } + } + + sprite.screen = pScreen; + sprite.hotPhys.x = x - panoramiXdataPtr[0].x; + sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + x -= panoramiXdataPtr[pScreen->myNum].x; + y -= panoramiXdataPtr[pScreen->myNum].y; + + return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); +} + + +static void +XineramaConstrainCursor(void) +{ + ScreenPtr pScreen = sprite.screen; + BoxRec newBox = sprite.physLimits; + + /* Translate the constraining box to the screen + the sprite is actually on */ + newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + + (* pScreen->ConstrainCursor)(pScreen, &newBox); +} + +static void +XineramaCheckPhysLimits( + CursorPtr cursor, + Bool generateEvents +){ + HotSpot new; + + if (!cursor) + return; + + new = sprite.hotPhys; + + /* I don't care what the DDX has to say about it */ + sprite.physLimits = sprite.hotLimits; + + /* constrain the pointer to those limits */ + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) /* more work if the shape is a mess */ + ConfineToShape(sprite.hotShape, &new.x, &new.y); + + if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + XineramaSetCursorPosition (new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } + + /* Tell DDX what the limits are */ + XineramaConstrainCursor(); +} + + +static Bool +XineramaSetWindowPntrs(WindowPtr pWin) +{ + if(pWin == WindowTable[0]) { + memcpy(sprite.windows, WindowTable, + PanoramiXNumScreens*sizeof(WindowPtr)); + } else { + PanoramiXRes *win; + int i; + + win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); + + if(!win) + return FALSE; + + for(i = 0; i < PanoramiXNumScreens; i++) { + sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!sprite.windows[i]) /* window is being unmapped */ + return FALSE; + } + } + return TRUE; +} + +static void +XineramaCheckVirtualMotion( + QdEventPtr qe, + WindowPtr pWin +){ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + int x, y, off_x, off_y, i; + BoxRec lims; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg2, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; + + if (REGION_NUM_RECTS(&sprite.Reg2) > 1) + ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +} + + +static Bool +XineramaCheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + /* Motion events entering DIX get translated to Screen 0 + coordinates. Replayed events have already been + translated since they've entered DIX before */ + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + XineramaSetCursorPosition( + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + + +static void +XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +{ + + if (syncEvents.playingEvents) + { + XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + int x, y, off_x, off_y, i; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg1, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + + if(REGION_NUM_RECTS(&sprite.Reg1) > 1) + sprite.hotShape = &sprite.Reg1; + else + sprite.hotShape = NullRegion; + + sprite.confined = FALSE; + sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + + XineramaCheckPhysLimits(sprite.current, generateEvents); + } +} + + +static void +XineramaChangeToCursor(CursorPtr cursor) +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(cursor, FALSE); + (*sprite.screen->DisplayCursor)(sprite.screen, cursor); + sprite.current = cursor; + } +} + + +#endif /* PANORAMIX */ + +void +SetMaskForEvent(mask, event) + Mask mask; + int event; +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +void +SetCriticalEvent(event) + int event; +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +#if NeedFunctionPrototypes +SyntheticMotion(int x, int y) +#else +SyntheticMotion(x, y) + int x, y; +#endif +{ + xEvent xE; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x; + y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +#if NeedFunctionPrototypes +ConfineToShape(RegionPtr shape, int *px, int *py) +#else +ConfineToShape(shape, px, py) + RegionPtr shape; + int *px, *py; +#endif +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +#if NeedFunctionPrototypes +CheckPhysLimits( + CursorPtr cursor, + Bool generateEvents, + Bool confineToScreen, + ScreenPtr pScreen) +#else +CheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen) + CursorPtr cursor; + Bool generateEvents; + Bool confineToScreen; + ScreenPtr pScreen; +#endif +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +#if NeedFunctionPrototypes +CheckVirtualMotion( + register QdEventPtr qe, + register WindowPtr pWin) +#else +CheckVirtualMotion(qe, pWin) + register QdEventPtr qe; + register WindowPtr pWin; +#endif +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaCheckVirtualMotion(qe, pWin); + return; + } +#endif + if (qe) + { + sprite.hot.pScreen = qe->pScreen; + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaConfineCursorToWindow(pWin, generateEvents); + return; + } +#endif + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +#if NeedFunctionPrototypes +ChangeToCursor(CursorPtr cursor) +#else +ChangeToCursor(cursor) + CursorPtr cursor; +#endif +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaChangeToCursor(cursor); + return; + } +#endif + + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, sprite.confined, + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + sprite.current = cursor; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(a, b) + register WindowPtr a, b; +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +#if NeedFunctionPrototypes +PostNewCursor(void) +#else +PostNewCursor() +#endif +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +void +GetSpritePosition(px, py) + int *px, *py; +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#ifdef PANORAMIX +int +XineramaGetCursorScreen() +{ + if(!noPanoramiXExtension) { + return sprite.screen->myNum; + } else { + return 0; + } +} +#endif /* PANORAMIX */ + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +#if NeedFunctionPrototypes +MonthChangedOrBadTime(register xEvent *xE) +#else +MonthChangedOrBadTime(xE) + register xEvent *xE; +#endif +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) + currentTime.months++; + else + XE_KBPTR.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(xE) + register xEvent *xE; +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xE, device, count) + xEvent *xE; + DeviceIntPtr device; + int count; +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + } +#endif + sprite.hotPhys.x = XE_KBPTR.rootX; + sprite.hotPhys.y = XE_KBPTR.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = XE_KBPTR.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +#if NeedFunctionPrototypes +PlayReleasedEvents(void) +#else +PlayReleasedEvents() +#endif +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +#if NeedFunctionPrototypes +FreezeThaw(register DeviceIntPtr dev, Bool frozen) +#else +FreezeThaw(dev, frozen) + register DeviceIntPtr dev; + Bool frozen; +#endif +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + + w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < spriteTraceGood; i++) + { + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + } + goto playmore; + } + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +#ifdef RANDR +void +ScreenRestructured (ScreenPtr pScreen) +{ + GrabPtr grab; + + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +CheckGrabForSyncs(thisDev, thisMode, otherMode) + register DeviceIntPtr thisDev; + Bool thisMode, otherMode; +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(mouse, grab, time, autoGrab) + register GrabPtr grab; + register DeviceIntPtr mouse; + TimeStamp time; + Bool autoGrab; +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + + #ifdef NXAGENT_SERVER + + /* + * If grab is synchronous, events are delivered to clients only if they send + * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the + * delivered event is saved in a queue and replayed later, when grab is released. + * We should export sync grab to X as async in order to avoid events to be + * queued twice, in the agent and in the X server. This solution have a drawback: + * replayed events are not delivered to that application that are not clients of + * the agent. + * A different solution could be to make the grab asynchronous in the agent and + * to export it as synchronous. But this seems to be less safe. + * + * To make internal grab asynchronous, change previous line as follows. + * + * if (nxagentOption(Rootless)) + * { + * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode); + * } + * else + * { + * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + * } + */ + + if (nxagentOption(Rootless) == 1) + { + /* + * FIXME: We should use the correct value + * for the cursor. Temporarily we set it + * to None. + */ + + int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, + nxagentCollectGrabPointerPredicate); + + NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window), + 1, grab -> eventMask & PointerGrabMask, + GrabModeAsync, GrabModeAsync, (grab -> confineTo) ? + nxagentWindow(grab -> confineTo) : None, + None, CurrentTime); + } + + #endif +} + +void +DeactivatePointerGrab(mouse) + register DeviceIntPtr mouse; +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); + + #ifdef NXAGENT_SERVER + + if (nxagentOption(Rootless) == 1) + { + XUngrabPointer(nxagentDisplay, CurrentTime); + + if (sprite.win == ROOT) + { + mouse -> button -> state &= + ~(Button1Mask | Button2Mask | Button3Mask | + Button4Mask | Button5Mask); + } + } + + #endif +} + +void +ActivateKeyboardGrab(keybd, grab, time, passive) + register DeviceIntPtr keybd; + GrabPtr grab; + TimeStamp time; + Bool passive; +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(keybd) + register DeviceIntPtr keybd; +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(client, time, thisDev, newState) + ClientPtr client; + TimeStamp time; + register DeviceIntPtr thisDev; + int newState; +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(client) + register ClientPtr client; +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * This is not necessary if we export grab to X as asynchronous. + * + * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard && + * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard) + * { + * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime); + * } + */ + + return Success; +} + +void +ReleaseActiveGrabs(client) + ClientPtr client; +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +int +TryClientEvents (client, pEvents, count, mask, filter, grab) + ClientPtr client; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask mask, filter; +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); + fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint + ((deviceKeyButtonPointer*)pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { +#ifdef SMART_SCHEDULE + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; +#endif + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx) + register WindowPtr pWin; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask filter; + int mskidx; +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask = 0; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) && + deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +#ifdef PANORAMIX +static int +XineramaTryClientEventsResult( + ClientPtr client, + GrabPtr grab, + Mask mask, + Mask filter +){ + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) return -1; + else return 1; + } + return 0; +} +#endif + +int +MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient) + register WindowPtr pWin; + xEvent *pEvents; + int count; + Mask filter; + ClientPtr dontClient; +{ + register OtherClients *other; + + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + wClient(pWin), NullGrab, pWin->eventMask, filter); +#endif + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + rClient(other), NullGrab, other->mask, filter); +#endif + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +#if NeedFunctionPrototypes +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +#else +FixUpEventFromWindow(xE, pWin, child, calcChild) + xEvent *xE; + WindowPtr pWin; + Window child; + Bool calcChild; +#endif +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xTrue; + XE_KBPTR.child = child; + XE_KBPTR.eventX = + XE_KBPTR.rootX - pWin->drawable.x; + XE_KBPTR.eventY = + XE_KBPTR.rootY - pWin->drawable.y; + } + else + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + } +} + +int +DeliverDeviceEvents(pWin, xE, grab, stopAt, dev, count) + register WindowPtr pWin, stopAt; + register xEvent *xE; + GrabPtr grab; + DeviceIntPtr dev; + int count; +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +int +DeliverEvents(pWin, xE, count, otherParent) + register WindowPtr pWin, otherParent; + register xEvent *xE; + int count; +{ + Mask filter; + int deliveries; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return count; +#endif + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + + +static Bool +PointInBorderSize(WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(POINT_IN_REGION(sprite.screen, + &sprite.windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + &box)) + return TRUE; + } + } +#endif + return FALSE; +} + +static WindowPtr +#if NeedFunctionPrototypes +XYToWindow(int x, int y) +#else +XYToWindow(x, y) + int x, y; +#endif +{ + register WindowPtr pWin; + + spriteTraceGood = 1; /* root window still there */ + + if (nxagentOption(Rootless)) + { + if (nxagentLastEnteredWindow == NULL) + { + return ROOT; + } + + pWin = ROOT->lastChild; + + while (pWin && pWin != ROOT->firstChild && pWin != nxagentLastEnteredWindow) + { + pWin = pWin->prevSib; + } + } + else + { + pWin = ROOT->firstChild; + } + + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +#if NeedFunctionPrototypes +CheckMotion(xEvent *xE) +#else +CheckMotion(xE) + xEvent *xE; +#endif +{ + WindowPtr prevSpriteWin = sprite.win; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaCheckMotion(xE); +#endif + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif + sprite.hotPhys = sprite.hot; + + /* + * This code force cursor position to be inside the + * root window of the agent. We can't view a reason + * to do this and it interacts in an undesirable way + * with toggling fullscreen. + * + * if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + * (sprite.hotPhys.y != XE_KBPTR.rootY)) + * { + * (*sprite.hotPhys.pScreen->SetCursorPosition)( + * sprite.hotPhys.pScreen, + * sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + * } + */ + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +void +DefineInitialRootWindow(win) + register WindowPtr win; +{ + register ScreenPtr pScreen = win->drawable.pScreen; + extern void nxagentInitViewportFrame(ScreenPtr, WindowPtr); + extern int nxagentShadowInit(ScreenPtr, WindowPtr); + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; + sprite.win = win; + sprite.current = wCursor (win); + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.confineWin = NullWindow; + sprite.screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_INIT(pScreen, &sprite.Reg1, NullBox, 1); + REGION_INIT(pScreen, &sprite.Reg2, NullBox, 1); + } +#endif + + nxagentInitViewportFrame(pScreen, win); + + if (nxagentOption(Shadow)) + { + if (nxagentShadowInit(pScreen, win) == -1) + { + GiveUp(0); + } + } +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +/*ARGSUSED*/ +void +WindowHasNewCursor(pWin) + WindowPtr pWin; +{ + PostNewCursor(); +} + +void +NewCurrentScreen(newScreen, x, y) + ScreenPtr newScreen; + int x,y; +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + panoramiXdataPtr[0].x; + sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + panoramiXdataPtr[0].y; + if (newScreen != sprite.screen) { + sprite.screen = newScreen; + /* Make sure we tell the DDX to update its copy of the screen */ + if(sprite.confineWin) + XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + else + XineramaConfineCursorToWindow(WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get + told of the pointer warp so we reposition it here */ + if(!syncEvents.playingEvents) + (*sprite.screen->SetCursorPosition)(sprite.screen, + sprite.hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x, + sprite.hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + } + } else +#endif + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +#ifdef PANORAMIX + +static Bool +XineramaPointInWindowIsVisible( + WindowPtr pWin, + int x, + int y +) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + int i, xoff, yoff; + + if (!pWin->realized) return FALSE; + + if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + if(!XineramaSetWindowPntrs(pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; + + for(i = 1; i < PanoramiXNumScreens; i++) { + pWin = sprite.windows[i]; + pScreen = pWin->drawable.pScreen; + x = xoff - panoramiXdataPtr[i].x; + y = yoff - panoramiXdataPtr[i].y; + + if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + } + + return FALSE; +} + +static int +XineramaWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + + REQUEST(xWarpPointerReq); + + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if(source == WindowTable[0]) { + winX -= panoramiXdataPtr[0].x; + winY -= panoramiXdataPtr[0].y; + } + if (x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !XineramaPointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) { + x = dest->drawable.x; + y = dest->drawable.y; + if(dest == WindowTable[0]) { + x -= panoramiXdataPtr[0].x; + y -= panoramiXdataPtr[0].y; + } + } + + x += stuff->dstX; + y += stuff->dstY; + + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + + XineramaSetCursorPosition(x, y, TRUE); + + return Success; +} + +#endif + + +int +ProcWarpPointer(client) + ClientPtr client; +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaWarpPointer(client); +#endif + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = sprite.hotPhys.pScreen; + + x += stuff->dstX; + y += stuff->dstY; + + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#if defined(SHAPE) + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + return TRUE; + } + } +#endif + return FALSE; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +#if NeedFunctionPrototypes +CheckPassiveGrabsOnWindow( + WindowPtr pWin, + register DeviceIntPtr device, + register xEvent *xE, + int count) +#else +CheckPassiveGrabsOnWindow(pWin, device, xE, count) + WindowPtr pWin; + register DeviceIntPtr device; + register xEvent *xE; + int count; +#endif +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if (device == grab->modifierDevice && + (xE->u.u.type == KeyPress +#ifdef XINPUT + || xE->u.u.type == DeviceKeyPress +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) + { +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + XE_KBPTR.state &= 0x1f00; + XE_KBPTR.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/* +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(device, xE, checkFirst, count) + register DeviceIntPtr device; + register xEvent *xE; + int checkFirst; + int count; +{ + register int i; + register WindowPtr pWin = NULL; + register FocusClassPtr focus = device->focus; + + if ((xE->u.u.type == ButtonPress +#ifdef XINPUT + || xE->u.u.type == DeviceButtonPress +#endif + ) && device->button->buttonsDown != 1) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(keybd, xE, window, count) + xEvent *xE; + DeviceIntPtr keybd; + WindowPtr window; + int count; +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(xE, thisDev, deactivateGrab, count) + register xEvent *xE; + register DeviceIntPtr thisDev; + Bool deactivateGrab; + int count; +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (xE, keybd, count) +#else +ProcessKeyboardEvent (xE, keybd, count) +#endif + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); +} + +#ifdef XKB +/* This function is used to set the key pressed or key released state - + this is only used when the pressing of keys does not cause + CoreProcessKeyEvent to be called, as in for example Mouse Keys. +*/ +void +FixKeyState (xE, keybd) + register xEvent *xE; + register DeviceIntPtr keybd; +{ + int key, bit; + register BYTE *kptr; + register KeyClassPtr keyc = keybd->key; + + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("FixKeyState: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + *kptr |= bit; + break; + case KeyRelease: + *kptr &= ~bit; + break; + default: + FatalError("Impossible keyboard event"); + } +} +#endif + +void +#ifdef XKB +CoreProcessPointerEvent (xE, mouse, count) +#else +ProcessPointerEvent (xE, mouse, count) +#endif + register xEvent *xE; + register DeviceIntPtr mouse; + int count; +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi; + + xkbi = inputInfo.keyboard->key->xkbInfo; +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + if (!(*kptr & bit)) + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (*kptr & bit) + --butc->buttonsDown; + if (!butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +int +OtherClientGone(value, id) + pointer value; /* must conform to DeleteType */ + XID id; +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(pWin, client, mask) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#ifdef SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#ifdef SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +/*ARGSUSED*/ +int +EventSuppressForWindow(pWin, client, mask, checkOptional) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; + Bool *checkOptional; +{ + register int i, free; + + if ((mask & ~PropagateMask) && !permitOldBugs) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +#if NeedFunctionPrototypes +CommonAncestor( + register WindowPtr a, + register WindowPtr b) +#else +CommonAncestor(a, b) + register WindowPtr a, b; +#endif +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +#if NeedFunctionPrototypes +EnterLeaveEvent( + int type, + int mode, + int detail, + register WindowPtr pWin, + Window child) +#else +EnterLeaveEvent(type, mode, detail, pWin, child) + int type, mode, detail; + register WindowPtr pWin; + Window child; +#endif +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XCSECURITY + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +#if NeedFunctionPrototypes +EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +#else +EnterNotifies(ancestor, child, mode, detail) + WindowPtr ancestor, child; + int mode, detail; +#endif +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +#if NeedFunctionPrototypes +LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +#else +LeaveNotifies(child, ancestor, mode, detail) + WindowPtr child, ancestor; + int detail, mode; +#endif +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +#if NeedFunctionPrototypes +DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +#else +DoEnterLeaveEvents(fromWin, toWin, mode) + WindowPtr fromWin, toWin; + int mode; +#endif +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +#if NeedFunctionPrototypes +FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin) +#else +FocusEvent(dev, type, mode, detail, pWin) + DeviceIntPtr dev; + int type, mode, detail; + register WindowPtr pWin; +#endif +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XCSECURITY + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +#if NeedFunctionPrototypes +FocusInEvents( + DeviceIntPtr dev, + WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, + int mode, int detail, + Bool doAncestor) +#else +FocusInEvents(dev, ancestor, child, skipChild, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr ancestor, child, skipChild; + int mode, detail; + Bool doAncestor; +#endif +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +#if NeedFunctionPrototypes +FocusOutEvents( + DeviceIntPtr dev, + WindowPtr child, WindowPtr ancestor, + int mode, int detail, + Bool doAncestor) +#else +FocusOutEvents(dev, child, ancestor, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr child, ancestor; + int mode; + int detail; + Bool doAncestor; +#endif +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(dev, fromWin, toWin, mode) + DeviceIntPtr dev; + WindowPtr fromWin, toWin; + int mode; +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; iparent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); + else +#endif + for (i=0; iparent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +#if NeedFunctionPrototypes +SetInputFocus( + ClientPtr client, + DeviceIntPtr dev, + Window focusID, + CARD8 revertTo, + Time ctime, + Bool followOK) +#else +SetInputFocus(client, dev, focusID, revertTo, ctime, followOK) + ClientPtr client; + DeviceIntPtr dev; + Window focusID; + CARD8 revertTo; + Time ctime; + Bool followOK; +#endif +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)(long)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(client) + ClientPtr client; +{ + xGetInputFocusReply rep; + /* REQUEST(xReq); */ + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(client) + ClientPtr client; +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(client, dev, this_mode, other_mode, grabWindow, ownerEvents, ctime, + mask, status) + register ClientPtr client; + register DeviceIntPtr dev; + unsigned this_mode; + unsigned other_mode; + Window grabWindow; + unsigned ownerEvents; + Time ctime; + Mask mask; + CARD8 *status; +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(client) + ClientPtr client; +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(client) + ClientPtr client; +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if(stuff->id == rep.root) { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +void +CloseDownEvents(void) +{ + xfree(spriteTrace); + spriteTrace = NULL; + spriteTraceSize = 0; +} + +int +ProcSendEvent(client) + ClientPtr client; +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + +#ifdef NXAGENT_CLIPBOARD + + if (stuff -> event.u.u.type == SelectionNotify) + { + extern int nxagentSendNotify(xEvent*); + if (nxagentSendNotify(&stuff->event) == 1) + return Success; + } +#endif + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32 && + !permitOldBugs) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(client) + ClientPtr client; +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(client) + ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, + NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + + +int +ProcGrabButton(client) + ClientPtr client; +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + permitOldBugs ? (Mask)(stuff->eventMask | + ButtonPressMask | ButtonReleaseMask) : + (Mask)stuff->eventMask, + (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, + (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers, + ButtonPress, stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(client) + ClientPtr client; +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(pWin, freeResources) + WindowPtr pWin; + Bool freeResources; +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/* Call this whenever some window at or below pWin has changed geometry */ + +/*ARGSUSED*/ +void +CheckCursorConfinement(pWin) + WindowPtr pWin; +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; +#endif + + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(confineTo)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(pWin, client) + WindowPtr pWin; + ClientPtr client; +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(client) + ClientPtr client; +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + Bool displayed; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; +#ifdef PANORAMIX + if(!noPanoramiXExtension) + displayed = (pscr == sprite.screen); + else +#endif + displayed = (pscr == sprite.hotPhys.pScreen); + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && displayed); + } + return (Success); +} + +void +WriteEventsToClient(pClient, count, events) + ClientPtr pClient; + int count; + xEvent *events; +{ +#ifdef PANORAMIX + xEvent eventCopy; +#endif + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + +#ifdef PANORAMIX + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + { + switch(events->u.u.type) { + case MotionNotify: + case ButtonPress: + case ButtonRelease: + case KeyPress: + case KeyRelease: + case EnterNotify: + case LeaveNotify: + /* + When multiple clients want the same event DeliverEventsToWindow + passes the same event structure multiple times so we can't + modify the one passed to us + */ + count = 1; /* should always be 1 */ + memcpy(&eventCopy, events, sizeof(xEvent)); + eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) + { + eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; + } + events = &eventCopy; + break; + default: break; + } + } +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXevents.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c.XF86.original new file mode 100644 index 000000000..ce8e53f92 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c.XF86.original @@ -0,0 +1,4637 @@ +/* $XFree86: xc/programs/Xserver/dix/events.c,v 3.46 2002/09/17 01:15:09 dawes Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) 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. * +* * +*****************************************************************/ + +/* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "globals.h" + +#ifdef XKB +#include "XKBsrv.h" +#if NeedFunctionPrototypes +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +#else +extern Bool XkbFilterEvents(); +#endif +#endif + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif + +#include "XIproto.h" +#include "exevents.h" +#include "extnsionst.h" + +#include "dixevents.h" +#include "dixgrabs.h" +#include "dispatch.h" + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the ButtonMotionMasks are equal + * to the corresponding ButtonMasks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define XE_KBPTR (xE->u.keyButtonPointer) + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +CallbackListPtr EventCallback; +CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +typedef struct { + int x, y; + ScreenPtr pScreen; +} HotSpot; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif +} sprite; /* info about the cursor sprite */ + +static void DoEnterLeaveEvents( +#if NeedFunctionPrototypes + WindowPtr /*fromWin*/, + WindowPtr /*toWin*/, + int /*mode*/ +#endif +); + +static WindowPtr XYToWindow( +#if NeedFunctionPrototypes + int /*x*/, + int /*y*/ +#endif +); + +extern int lastEvent; + +static Mask lastEventMask; + +#ifdef XINPUT +extern int DeviceMotionNotify; +#endif + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x7c /* key and button events */ +}; + +#ifdef PANORAMIX + +static void ConfineToShape(RegionPtr shape, int *px, int *py); +static void SyntheticMotion(int x, int y); +static void PostNewCursor(void); + +static Bool +XineramaSetCursorPosition( + int x, + int y, + Bool generateEvent +){ + ScreenPtr pScreen; + BoxRec box; + int i; + + /* x,y are in Screen 0 coordinates. We need to decide what Screen + to send the message too and what the coordinates relative to + that screen are. */ + + pScreen = sprite.screen; + x += panoramiXdataPtr[0].x; + y += panoramiXdataPtr[0].y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) + { + FOR_NSCREENS(i) + { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) + { + pScreen = screenInfo.screens[i]; + break; + } + } + } + + sprite.screen = pScreen; + sprite.hotPhys.x = x - panoramiXdataPtr[0].x; + sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + x -= panoramiXdataPtr[pScreen->myNum].x; + y -= panoramiXdataPtr[pScreen->myNum].y; + + return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); +} + + +static void +XineramaConstrainCursor(void) +{ + ScreenPtr pScreen = sprite.screen; + BoxRec newBox = sprite.physLimits; + + /* Translate the constraining box to the screen + the sprite is actually on */ + newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + + (* pScreen->ConstrainCursor)(pScreen, &newBox); +} + +static void +XineramaCheckPhysLimits( + CursorPtr cursor, + Bool generateEvents +){ + HotSpot new; + + if (!cursor) + return; + + new = sprite.hotPhys; + + /* I don't care what the DDX has to say about it */ + sprite.physLimits = sprite.hotLimits; + + /* constrain the pointer to those limits */ + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) /* more work if the shape is a mess */ + ConfineToShape(sprite.hotShape, &new.x, &new.y); + + if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + XineramaSetCursorPosition (new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } + + /* Tell DDX what the limits are */ + XineramaConstrainCursor(); +} + + +static Bool +XineramaSetWindowPntrs(WindowPtr pWin) +{ + if(pWin == WindowTable[0]) { + memcpy(sprite.windows, WindowTable, + PanoramiXNumScreens*sizeof(WindowPtr)); + } else { + PanoramiXRes *win; + int i; + + win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); + + if(!win) + return FALSE; + + for(i = 0; i < PanoramiXNumScreens; i++) { + sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!sprite.windows[i]) /* window is being unmapped */ + return FALSE; + } + } + return TRUE; +} + +static void +XineramaCheckVirtualMotion( + QdEventPtr qe, + WindowPtr pWin +){ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + int x, y, off_x, off_y, i; + BoxRec lims; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg2, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; + + if (REGION_NUM_RECTS(&sprite.Reg2) > 1) + ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +} + + +static Bool +XineramaCheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + /* Motion events entering DIX get translated to Screen 0 + coordinates. Replayed events have already been + translated since they've entered DIX before */ + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + XineramaSetCursorPosition( + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + + +static void +XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +{ + + if (syncEvents.playingEvents) + { + XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + int x, y, off_x, off_y, i; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg1, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + + if(REGION_NUM_RECTS(&sprite.Reg1) > 1) + sprite.hotShape = &sprite.Reg1; + else + sprite.hotShape = NullRegion; + + sprite.confined = FALSE; + sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + + XineramaCheckPhysLimits(sprite.current, generateEvents); + } +} + + +static void +XineramaChangeToCursor(CursorPtr cursor) +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(cursor, FALSE); + (*sprite.screen->DisplayCursor)(sprite.screen, cursor); + sprite.current = cursor; + } +} + + +#endif /* PANORAMIX */ + +void +SetMaskForEvent(mask, event) + Mask mask; + int event; +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +void +SetCriticalEvent(event) + int event; +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +#if NeedFunctionPrototypes +SyntheticMotion(int x, int y) +#else +SyntheticMotion(x, y) + int x, y; +#endif +{ + xEvent xE; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x; + y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +#if NeedFunctionPrototypes +ConfineToShape(RegionPtr shape, int *px, int *py) +#else +ConfineToShape(shape, px, py) + RegionPtr shape; + int *px, *py; +#endif +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +#if NeedFunctionPrototypes +CheckPhysLimits( + CursorPtr cursor, + Bool generateEvents, + Bool confineToScreen, + ScreenPtr pScreen) +#else +CheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen) + CursorPtr cursor; + Bool generateEvents; + Bool confineToScreen; + ScreenPtr pScreen; +#endif +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +#if NeedFunctionPrototypes +CheckVirtualMotion( + register QdEventPtr qe, + register WindowPtr pWin) +#else +CheckVirtualMotion(qe, pWin) + register QdEventPtr qe; + register WindowPtr pWin; +#endif +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaCheckVirtualMotion(qe, pWin); + return; + } +#endif + if (qe) + { + sprite.hot.pScreen = qe->pScreen; + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaConfineCursorToWindow(pWin, generateEvents); + return; + } +#endif + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +#if NeedFunctionPrototypes +ChangeToCursor(CursorPtr cursor) +#else +ChangeToCursor(cursor) + CursorPtr cursor; +#endif +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaChangeToCursor(cursor); + return; + } +#endif + + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, sprite.confined, + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + sprite.current = cursor; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(a, b) + register WindowPtr a, b; +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +#if NeedFunctionPrototypes +PostNewCursor(void) +#else +PostNewCursor() +#endif +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +void +GetSpritePosition(px, py) + int *px, *py; +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#ifdef PANORAMIX +int +XineramaGetCursorScreen() +{ + if(!noPanoramiXExtension) { + return sprite.screen->myNum; + } else { + return 0; + } +} +#endif /* PANORAMIX */ + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +#if NeedFunctionPrototypes +MonthChangedOrBadTime(register xEvent *xE) +#else +MonthChangedOrBadTime(xE) + register xEvent *xE; +#endif +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) + currentTime.months++; + else + XE_KBPTR.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(xE) + register xEvent *xE; +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xE, device, count) + xEvent *xE; + DeviceIntPtr device; + int count; +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + } +#endif + sprite.hotPhys.x = XE_KBPTR.rootX; + sprite.hotPhys.y = XE_KBPTR.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = XE_KBPTR.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +#if NeedFunctionPrototypes +PlayReleasedEvents(void) +#else +PlayReleasedEvents() +#endif +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +#if NeedFunctionPrototypes +FreezeThaw(register DeviceIntPtr dev, Bool frozen) +#else +FreezeThaw(dev, frozen) + register DeviceIntPtr dev; + Bool frozen; +#endif +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + + w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < spriteTraceGood; i++) + { + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + } + goto playmore; + } + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +#ifdef RANDR +void +ScreenRestructured (ScreenPtr pScreen) +{ + GrabPtr grab; + + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +CheckGrabForSyncs(thisDev, thisMode, otherMode) + register DeviceIntPtr thisDev; + Bool thisMode, otherMode; +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(mouse, grab, time, autoGrab) + register GrabPtr grab; + register DeviceIntPtr mouse; + TimeStamp time; + Bool autoGrab; +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); +} + +void +DeactivatePointerGrab(mouse) + register DeviceIntPtr mouse; +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); +} + +void +ActivateKeyboardGrab(keybd, grab, time, passive) + register DeviceIntPtr keybd; + GrabPtr grab; + TimeStamp time; + Bool passive; +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(keybd) + register DeviceIntPtr keybd; +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(client, time, thisDev, newState) + ClientPtr client; + TimeStamp time; + register DeviceIntPtr thisDev; + int newState; +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(client) + register ClientPtr client; +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + return Success; +} + +void +ReleaseActiveGrabs(client) + ClientPtr client; +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +int +TryClientEvents (client, pEvents, count, mask, filter, grab) + ClientPtr client; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask mask, filter; +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); + fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint + ((deviceKeyButtonPointer*)pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { +#ifdef SMART_SCHEDULE + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; +#endif + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx) + register WindowPtr pWin; + GrabPtr grab; + xEvent *pEvents; + int count; + Mask filter; + int mskidx; +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask = 0; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) && + deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +#ifdef PANORAMIX +static int +XineramaTryClientEventsResult( + ClientPtr client, + GrabPtr grab, + Mask mask, + Mask filter +){ + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) return -1; + else return 1; + } + return 0; +} +#endif + +int +MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient) + register WindowPtr pWin; + xEvent *pEvents; + int count; + Mask filter; + ClientPtr dontClient; +{ + register OtherClients *other; + + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + wClient(pWin), NullGrab, pWin->eventMask, filter); +#endif + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + rClient(other), NullGrab, other->mask, filter); +#endif + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +#if NeedFunctionPrototypes +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +#else +FixUpEventFromWindow(xE, pWin, child, calcChild) + xEvent *xE; + WindowPtr pWin; + Window child; + Bool calcChild; +#endif +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xTrue; + XE_KBPTR.child = child; + XE_KBPTR.eventX = + XE_KBPTR.rootX - pWin->drawable.x; + XE_KBPTR.eventY = + XE_KBPTR.rootY - pWin->drawable.y; + } + else + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + } +} + +int +DeliverDeviceEvents(pWin, xE, grab, stopAt, dev, count) + register WindowPtr pWin, stopAt; + register xEvent *xE; + GrabPtr grab; + DeviceIntPtr dev; + int count; +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +int +DeliverEvents(pWin, xE, count, otherParent) + register WindowPtr pWin, otherParent; + register xEvent *xE; + int count; +{ + Mask filter; + int deliveries; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return count; +#endif + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + + +static Bool +PointInBorderSize(WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(POINT_IN_REGION(sprite.screen, + &sprite.windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + &box)) + return TRUE; + } + } +#endif + return FALSE; +} + +static WindowPtr +#if NeedFunctionPrototypes +XYToWindow(int x, int y) +#else +XYToWindow(x, y) + int x, y; +#endif +{ + register WindowPtr pWin; + + spriteTraceGood = 1; /* root window still there */ + pWin = ROOT->firstChild; + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +#if NeedFunctionPrototypes +CheckMotion(xEvent *xE) +#else +CheckMotion(xE) + xEvent *xE; +#endif +{ + WindowPtr prevSpriteWin = sprite.win; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaCheckMotion(xE); +#endif + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } + sprite.hot.x = XE_KBPTR.rootX; + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + (*sprite.hotPhys.pScreen->SetCursorPosition)( + sprite.hotPhys.pScreen, + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +void +DefineInitialRootWindow(win) + register WindowPtr win; +{ + register ScreenPtr pScreen = win->drawable.pScreen; + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; + sprite.win = win; + sprite.current = wCursor (win); + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.confineWin = NullWindow; + sprite.screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_INIT(pScreen, &sprite.Reg1, NullBox, 1); + REGION_INIT(pScreen, &sprite.Reg2, NullBox, 1); + } +#endif +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +/*ARGSUSED*/ +void +WindowHasNewCursor(pWin) + WindowPtr pWin; +{ + PostNewCursor(); +} + +void +NewCurrentScreen(newScreen, x, y) + ScreenPtr newScreen; + int x,y; +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + panoramiXdataPtr[0].x; + sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + panoramiXdataPtr[0].y; + if (newScreen != sprite.screen) { + sprite.screen = newScreen; + /* Make sure we tell the DDX to update its copy of the screen */ + if(sprite.confineWin) + XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + else + XineramaConfineCursorToWindow(WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get + told of the pointer warp so we reposition it here */ + if(!syncEvents.playingEvents) + (*sprite.screen->SetCursorPosition)(sprite.screen, + sprite.hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x, + sprite.hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + } + } else +#endif + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +#ifdef PANORAMIX + +static Bool +XineramaPointInWindowIsVisible( + WindowPtr pWin, + int x, + int y +) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + int i, xoff, yoff; + + if (!pWin->realized) return FALSE; + + if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + if(!XineramaSetWindowPntrs(pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; + + for(i = 1; i < PanoramiXNumScreens; i++) { + pWin = sprite.windows[i]; + pScreen = pWin->drawable.pScreen; + x = xoff - panoramiXdataPtr[i].x; + y = yoff - panoramiXdataPtr[i].y; + + if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + } + + return FALSE; +} + +static int +XineramaWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + + REQUEST(xWarpPointerReq); + + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if(source == WindowTable[0]) { + winX -= panoramiXdataPtr[0].x; + winY -= panoramiXdataPtr[0].y; + } + if (x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !XineramaPointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) { + x = dest->drawable.x; + y = dest->drawable.y; + if(dest == WindowTable[0]) { + x -= panoramiXdataPtr[0].x; + y -= panoramiXdataPtr[0].y; + } + } + + x += stuff->dstX; + y += stuff->dstY; + + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + + XineramaSetCursorPosition(x, y, TRUE); + + return Success; +} + +#endif + + +int +ProcWarpPointer(client) + ClientPtr client; +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaWarpPointer(client); +#endif + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = sprite.hotPhys.pScreen; + + x += stuff->dstX; + y += stuff->dstY; + + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#if defined(SHAPE) + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + return TRUE; + } + } +#endif + return FALSE; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +#if NeedFunctionPrototypes +CheckPassiveGrabsOnWindow( + WindowPtr pWin, + register DeviceIntPtr device, + register xEvent *xE, + int count) +#else +CheckPassiveGrabsOnWindow(pWin, device, xE, count) + WindowPtr pWin; + register DeviceIntPtr device; + register xEvent *xE; + int count; +#endif +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if (device == grab->modifierDevice && + (xE->u.u.type == KeyPress +#ifdef XINPUT + || xE->u.u.type == DeviceKeyPress +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) + { +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + XE_KBPTR.state &= 0x1f00; + XE_KBPTR.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/* +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(device, xE, checkFirst, count) + register DeviceIntPtr device; + register xEvent *xE; + int checkFirst; + int count; +{ + register int i; + register WindowPtr pWin = NULL; + register FocusClassPtr focus = device->focus; + + if ((xE->u.u.type == ButtonPress +#ifdef XINPUT + || xE->u.u.type == DeviceButtonPress +#endif + ) && device->button->buttonsDown != 1) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(keybd, xE, window, count) + xEvent *xE; + DeviceIntPtr keybd; + WindowPtr window; + int count; +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(xE, thisDev, deactivateGrab, count) + register xEvent *xE; + register DeviceIntPtr thisDev; + Bool deactivateGrab; + int count; +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (xE, keybd, count) +#else +ProcessKeyboardEvent (xE, keybd, count) +#endif + register xEvent *xE; + register DeviceIntPtr keybd; + int count; +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); +} + +#ifdef XKB +/* This function is used to set the key pressed or key released state - + this is only used when the pressing of keys does not cause + CoreProcessKeyEvent to be called, as in for example Mouse Keys. +*/ +void +FixKeyState (xE, keybd) + register xEvent *xE; + register DeviceIntPtr keybd; +{ + int key, bit; + register BYTE *kptr; + register KeyClassPtr keyc = keybd->key; + + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("FixKeyState: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + *kptr |= bit; + break; + case KeyRelease: + *kptr &= ~bit; + break; + default: + FatalError("Impossible keyboard event"); + } +} +#endif + +void +#ifdef XKB +CoreProcessPointerEvent (xE, mouse, count) +#else +ProcessPointerEvent (xE, mouse, count) +#endif + register xEvent *xE; + register DeviceIntPtr mouse; + int count; +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + if (!(*kptr & bit)) + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (*kptr & bit) + --butc->buttonsDown; + if (!butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +int +OtherClientGone(value, id) + pointer value; /* must conform to DeleteType */ + XID id; +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(pWin, client, mask) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#ifdef SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#ifdef SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +/*ARGSUSED*/ +int +EventSuppressForWindow(pWin, client, mask, checkOptional) + register WindowPtr pWin; + register ClientPtr client; + Mask mask; + Bool *checkOptional; +{ + register int i, free; + + if ((mask & ~PropagateMask) && !permitOldBugs) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +#if NeedFunctionPrototypes +CommonAncestor( + register WindowPtr a, + register WindowPtr b) +#else +CommonAncestor(a, b) + register WindowPtr a, b; +#endif +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +#if NeedFunctionPrototypes +EnterLeaveEvent( + int type, + int mode, + int detail, + register WindowPtr pWin, + Window child) +#else +EnterLeaveEvent(type, mode, detail, pWin, child) + int type, mode, detail; + register WindowPtr pWin; + Window child; +#endif +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XCSECURITY + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +#if NeedFunctionPrototypes +EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +#else +EnterNotifies(ancestor, child, mode, detail) + WindowPtr ancestor, child; + int mode, detail; +#endif +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +#if NeedFunctionPrototypes +LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +#else +LeaveNotifies(child, ancestor, mode, detail) + WindowPtr child, ancestor; + int detail, mode; +#endif +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +#if NeedFunctionPrototypes +DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +#else +DoEnterLeaveEvents(fromWin, toWin, mode) + WindowPtr fromWin, toWin; + int mode; +#endif +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +#if NeedFunctionPrototypes +FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin) +#else +FocusEvent(dev, type, mode, detail, pWin) + DeviceIntPtr dev; + int type, mode, detail; + register WindowPtr pWin; +#endif +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XCSECURITY + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +#if NeedFunctionPrototypes +FocusInEvents( + DeviceIntPtr dev, + WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, + int mode, int detail, + Bool doAncestor) +#else +FocusInEvents(dev, ancestor, child, skipChild, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr ancestor, child, skipChild; + int mode, detail; + Bool doAncestor; +#endif +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +#if NeedFunctionPrototypes +FocusOutEvents( + DeviceIntPtr dev, + WindowPtr child, WindowPtr ancestor, + int mode, int detail, + Bool doAncestor) +#else +FocusOutEvents(dev, child, ancestor, mode, detail, doAncestor) + DeviceIntPtr dev; + WindowPtr child, ancestor; + int mode; + int detail; + Bool doAncestor; +#endif +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(dev, fromWin, toWin, mode) + DeviceIntPtr dev; + WindowPtr fromWin, toWin; + int mode; +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; iparent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); + else +#endif + for (i=0; iparent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +#if NeedFunctionPrototypes +SetInputFocus( + ClientPtr client, + DeviceIntPtr dev, + Window focusID, + CARD8 revertTo, + Time ctime, + Bool followOK) +#else +SetInputFocus(client, dev, focusID, revertTo, ctime, followOK) + ClientPtr client; + DeviceIntPtr dev; + Window focusID; + CARD8 revertTo; + Time ctime; + Bool followOK; +#endif +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)(long)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(client) + ClientPtr client; +{ + xGetInputFocusReply rep; + /* REQUEST(xReq); */ + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(client) + ClientPtr client; +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(client, dev, this_mode, other_mode, grabWindow, ownerEvents, ctime, + mask, status) + register ClientPtr client; + register DeviceIntPtr dev; + unsigned this_mode; + unsigned other_mode; + Window grabWindow; + unsigned ownerEvents; + Time ctime; + Mask mask; + CARD8 *status; +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(client) + ClientPtr client; +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(client) + ClientPtr client; +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(client) + ClientPtr client; +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if(stuff->id == rep.root) { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +void +CloseDownEvents(void) +{ + xfree(spriteTrace); + spriteTrace = NULL; + spriteTraceSize = 0; +} + +int +ProcSendEvent(client) + ClientPtr client; +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32 && + !permitOldBugs) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(client) + ClientPtr client; +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(client) + ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, + NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + + +int +ProcGrabButton(client) + ClientPtr client; +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + permitOldBugs ? (Mask)(stuff->eventMask | + ButtonPressMask | ButtonReleaseMask) : + (Mask)stuff->eventMask, + (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, + (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers, + ButtonPress, stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(client) + ClientPtr client; +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(pWin, freeResources) + WindowPtr pWin; + Bool freeResources; +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/* Call this whenever some window at or below pWin has changed geometry */ + +/*ARGSUSED*/ +void +CheckCursorConfinement(pWin) + WindowPtr pWin; +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; +#endif + + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(confineTo)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(pWin, client) + WindowPtr pWin; + ClientPtr client; +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(client) + ClientPtr client; +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + Bool displayed; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; +#ifdef PANORAMIX + if(!noPanoramiXExtension) + displayed = (pscr == sprite.screen); + else +#endif + displayed = (pscr == sprite.hotPhys.pScreen); + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && displayed); + } + return (Success); +} + +void +WriteEventsToClient(pClient, count, events) + ClientPtr pClient; + int count; + xEvent *events; +{ +#ifdef PANORAMIX + xEvent eventCopy; +#endif + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + +#ifdef PANORAMIX + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + { + switch(events->u.u.type) { + case MotionNotify: + case ButtonPress: + case ButtonRelease: + case KeyPress: + case KeyRelease: + case EnterNotify: + case LeaveNotify: + /* + When multiple clients want the same event DeliverEventsToWindow + passes the same event structure multiple times so we can't + modify the one passed to us + */ + count = 1; /* should always be 1 */ + memcpy(&eventCopy, events, sizeof(xEvent)); + eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) + { + eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; + } + events = &eventCopy; + break; + default: break; + } + } +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXextension.c b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c new file mode 100644 index 000000000..295b885c2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c @@ -0,0 +1,528 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXextension.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "../../dix/dispatch.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#include "Trap.h" + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +ExtensionEntry * +AddExtension(char *name, int NumEvents, int NumErrors, + int (*MainProc)(ClientPtr c1), + int (*SwappedMainProc)(ClientPtr c2), + void (*CloseDownProc)(ExtensionEntry *e), + unsigned short (*MinorOpcodeProc)(ClientPtr c3)) +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry)); + if (!ext) + return((ExtensionEntry *) NULL); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + +#ifdef LBX + (void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase); +#endif + return(ext); +} + +Bool AddExtensionAlias(alias, ext) + char *alias; + ExtensionEntry *ext; +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; +#ifdef LBX + return LbxAddExtensionAlias(ext->index, alias); +#else + return TRUE; +#endif +} + +static int +FindExtension(char *extname, int len) +{ + int i, j; + + for (i=0; iname) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +/* + * CheckExtension returns the extensions[] entry for the requested + * extension name. Maybe this could just return a Bool instead? + */ +ExtensionEntry * +CheckExtension(const char *extname) +{ + int n; + + n = FindExtension((char*)extname, strlen(extname)); + if (n != -1) + return extensions[n]; + else + return NULL; +} + +void +DeclareExtensionSecurity(extname, secure) + char *extname; + Bool secure; +{ +#ifdef XCSECURITY + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + { + int majorop = extensions[i]->base; + extensions[i]->secure = secure; + if (secure) + { + UntrustedProcVector[majorop] = ProcVector[majorop]; + SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop]; + } + else + { + UntrustedProcVector[majorop] = ProcBadRequest; + SwappedUntrustedProcVector[majorop] = ProcBadRequest; + } + } +#endif +#ifdef LBX + LbxDeclareExtensionSecurity(extname, secure); +#endif +} + +unsigned short +StandardMinorOpcode(client) + ClientPtr client; +{ + return ((xReq *)client->requestBuffer)->data; +} + +unsigned short +MinorOpcodeOfRequest(client) + ClientPtr client; +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + +#ifdef LBX + LbxCloseDownExtensions(); +#endif + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; inum) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(client) + ClientPtr client; +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 + + /* + * Hide RENDER if our implementation + * is faulty. + */ + + || (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(client) + ClientPtr client; +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + /* + * Hide RENDER if our implementation + * is faulty. + */ + + if (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) + continue; + + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(name, pGC) + char *name; + GCPtr pGC; +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(name, pGC, proc) + char *name; + GC *pGC; + ExtensionLookupProc proc; +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(name, pScreen, proc) + char *name; + ScreenPtr pScreen; + ExtensionLookupProc proc; +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXextension.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c.NX.original new file mode 100644 index 000000000..295b885c2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c.NX.original @@ -0,0 +1,528 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXextension.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "../../dix/dispatch.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#include "Trap.h" + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +ExtensionEntry * +AddExtension(char *name, int NumEvents, int NumErrors, + int (*MainProc)(ClientPtr c1), + int (*SwappedMainProc)(ClientPtr c2), + void (*CloseDownProc)(ExtensionEntry *e), + unsigned short (*MinorOpcodeProc)(ClientPtr c3)) +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry)); + if (!ext) + return((ExtensionEntry *) NULL); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + +#ifdef LBX + (void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase); +#endif + return(ext); +} + +Bool AddExtensionAlias(alias, ext) + char *alias; + ExtensionEntry *ext; +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; +#ifdef LBX + return LbxAddExtensionAlias(ext->index, alias); +#else + return TRUE; +#endif +} + +static int +FindExtension(char *extname, int len) +{ + int i, j; + + for (i=0; iname) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +/* + * CheckExtension returns the extensions[] entry for the requested + * extension name. Maybe this could just return a Bool instead? + */ +ExtensionEntry * +CheckExtension(const char *extname) +{ + int n; + + n = FindExtension((char*)extname, strlen(extname)); + if (n != -1) + return extensions[n]; + else + return NULL; +} + +void +DeclareExtensionSecurity(extname, secure) + char *extname; + Bool secure; +{ +#ifdef XCSECURITY + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + { + int majorop = extensions[i]->base; + extensions[i]->secure = secure; + if (secure) + { + UntrustedProcVector[majorop] = ProcVector[majorop]; + SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop]; + } + else + { + UntrustedProcVector[majorop] = ProcBadRequest; + SwappedUntrustedProcVector[majorop] = ProcBadRequest; + } + } +#endif +#ifdef LBX + LbxDeclareExtensionSecurity(extname, secure); +#endif +} + +unsigned short +StandardMinorOpcode(client) + ClientPtr client; +{ + return ((xReq *)client->requestBuffer)->data; +} + +unsigned short +MinorOpcodeOfRequest(client) + ClientPtr client; +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + +#ifdef LBX + LbxCloseDownExtensions(); +#endif + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; inum) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(client) + ClientPtr client; +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 + + /* + * Hide RENDER if our implementation + * is faulty. + */ + + || (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(client) + ClientPtr client; +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + /* + * Hide RENDER if our implementation + * is faulty. + */ + + if (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) + continue; + + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(name, pGC) + char *name; + GCPtr pGC; +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(name, pGC, proc) + char *name; + GC *pGC; + ExtensionLookupProc proc; +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(name, pScreen, proc) + char *name; + ScreenPtr pScreen; + ExtensionLookupProc proc; +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXextension.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c.XF86.original new file mode 100644 index 000000000..36f053f02 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c.XF86.original @@ -0,0 +1,486 @@ +/* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "dispatch.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +ExtensionEntry * +AddExtension(char *name, int NumEvents, int NumErrors, + int (*MainProc)(ClientPtr c1), + int (*SwappedMainProc)(ClientPtr c2), + void (*CloseDownProc)(ExtensionEntry *e), + unsigned short (*MinorOpcodeProc)(ClientPtr c3)) +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry)); + if (!ext) + return((ExtensionEntry *) NULL); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + +#ifdef LBX + (void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase); +#endif + return(ext); +} + +Bool AddExtensionAlias(alias, ext) + char *alias; + ExtensionEntry *ext; +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; +#ifdef LBX + return LbxAddExtensionAlias(ext->index, alias); +#else + return TRUE; +#endif +} + +static int +FindExtension(char *extname, int len) +{ + int i, j; + + for (i=0; iname) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +/* + * CheckExtension returns the extensions[] entry for the requested + * extension name. Maybe this could just return a Bool instead? + */ +ExtensionEntry * +CheckExtension(const char *extname) +{ + int n; + + n = FindExtension((char*)extname, strlen(extname)); + if (n != -1) + return extensions[n]; + else + return NULL; +} + +void +DeclareExtensionSecurity(extname, secure) + char *extname; + Bool secure; +{ +#ifdef XCSECURITY + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + { + int majorop = extensions[i]->base; + extensions[i]->secure = secure; + if (secure) + { + UntrustedProcVector[majorop] = ProcVector[majorop]; + SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop]; + } + else + { + UntrustedProcVector[majorop] = ProcBadRequest; + SwappedUntrustedProcVector[majorop] = ProcBadRequest; + } + } +#endif +#ifdef LBX + LbxDeclareExtensionSecurity(extname, secure); +#endif +} + +unsigned short +StandardMinorOpcode(client) + ClientPtr client; +{ + return ((xReq *)client->requestBuffer)->data; +} + +unsigned short +MinorOpcodeOfRequest(client) + ClientPtr client; +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + +#ifdef LBX + LbxCloseDownExtensions(); +#endif + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; inum) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(client) + ClientPtr client; +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(client) + ClientPtr client; +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(name, pGC) + char *name; + GCPtr pGC; +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(name, pGC, proc) + char *name; + GC *pGC; + ExtensionLookupProc proc; +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(name, pScreen, proc) + char *name; + ScreenPtr pScreen; + ExtensionLookupProc proc; +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c new file mode 100644 index 000000000..fe2f4aa6c --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c @@ -0,0 +1,550 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglxext.c" + +#else + +/* $XFree86: xc/programs/Xserver/GL/glx/glxext.c,v 1.8 2001/08/23 18:25:40 alanh Exp $ +** The contents of this file are subject to the GLX Public License Version 1.0 +** (the "License"). You may not use this file except in compliance with the +** License. You may obtain a copy of the License at Silicon Graphics, Inc., +** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +** or at http://www.sgi.com/software/opensource/glx/license.html. +** +** Software distributed under the License is distributed on an "AS IS" +** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY +** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR +** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific +** language governing rights and limitations under the License. +** +** The Original Software is GLX version 1.2 source code, released February, +** 1999. The developer of the Original Software is Silicon Graphics, Inc. +** Those portions of the Subject Software created by Silicon Graphics, Inc. +** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. +** +*/ + +#define NEED_REPLIES +#include "glxserver.h" +#include +#include +#include +#include "g_disptab.h" +#include "unpack.h" +#include "glxutil.h" +#include "glxext.h" +#include "micmap.h" + +#include "Trap.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +extern __GLXextensionInfo __glDDXExtensionInfo; + +__GLXextensionInfo *__glXExt = &__glDDXExtensionInfo; + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + (*__glXExt->resetExtension)(); + __glXScreenReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + + if (cl->returnBuf) __glXFree(cl->returnBuf); + if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); + if (cl->currentContexts) __glXFree(cl->currentContexts); + __glXMemset(cl, 0, sizeof(__GLXclientState)); + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + +} + +/* +** Reset state used to keep track of large (multi-request) commands. +*/ +void __glXResetLargeCommandStatus(__GLXclientState *cl) +{ + cl->largeCmdBytesSoFar = 0; + cl->largeCmdBytesTotal = 0; + cl->largeCmdRequestsSoFar = 0; + cl->largeCmdRequestsTotal = 0; +} + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + __glXDeassociateContext(cx, cx->glxPriv); + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + pGlxPixmap->idExists = False; + if (!pGlxPixmap->refcnt) { + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + __glXFree(pGlxPixmap); + } + + return True; +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + if (!cx->isDirect) { + if ((*cx->gc->exports.destroyContext)((__GLcontext *)cx->gc) == GL_FALSE) { + return GL_FALSE; + } + } + if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); + if (cx->selectBuf) __glXFree(cx->selectBuf); + __glXFree(cx); + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +/************************************************************************/ + +/* +** These routines can be used to check whether a particular GL command +** has caused an error. Specifically, we use them to check whether a +** given query has caused an error, in which case a zero-length data +** reply is sent to the client. +*/ + +static GLboolean errorOccured = GL_FALSE; + +/* +** The GL was will call this routine if an error occurs. +*/ +void __glXErrorCallBack(__GLinterface *gc, GLenum code) +{ + errorOccured = GL_TRUE; +} + +/* +** Clear the error flag before calling the GL command. +*/ +void __glXClearErrorOccured(void) +{ + errorOccured = GL_FALSE; +} + +/* +** Check if the GL command caused an error. +*/ +GLboolean __glXErrorOccured(void) +{ + return errorOccured; +} + +/************************************************************************/ + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef X11R5 + __glXContextRes = CreateNewResourceType(ContextGone); + __glXClientRes = CreateNewResourceType(ClientGone); + __glXPixmapRes = CreateNewResourceType(PixmapGone); +#else + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone); +#endif + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return __glXExt->type; +} + +/************************************************************************/ + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + (*__glXExt->setVisualConfigs)(nconfigs, configs, privates); +} + +static miInitVisualsProcPtr saveInitVisualsProc; + +Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, + int *nvisualp, int *ndepthp, + int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, + int preferredVis) +{ + Bool ret; + + if (saveInitVisualsProc) { + ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, + rootDepthp, defaultVisp, sizes, bitsPerRGB, + preferredVis); + if (!ret) + return False; + } + (*__glXExt->initVisuals)(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB); + return True; +} + +void +GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) +{ + saveInitVisualsProc = *initVisProc; + *initVisProc = GlxInitVisuals; +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/* +** Make a context the current one for the GL (in this implementation, there +** is only one instance of the GL, and we use it to serve all GL clients by +** switching it between different contexts). While we are at it, look up +** a context by its tag and return its (__GLXcontext *). +*/ +__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, + int *error) +{ + __GLXcontext *cx; + + /* + ** See if the context tag is legal; it is managed by the extension, + ** so if it's invalid, we have an implementation error. + */ + cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag); + if (!cx) { + cl->client->errorValue = tag; + *error = __glXBadContextTag; + return 0; + } + + if (!cx->isDirect) { + if (cx->glxPriv == NULL) { + /* + ** The drawable has vanished. It must be a window, because only + ** windows can be destroyed from under us; GLX pixmaps are + ** refcounted and don't go away until no one is using them. + */ + *error = __glXBadCurrentWindow; + return 0; + } + } + + if (cx == __glXLastContext) { + /* No need to re-bind */ + return cx; + } + + /* Make this context the current one for the GL. */ + if (!cx->isDirect) { + if (!(*cx->gc->exports.forceCurrent)((__GLcontext *)cx->gc)) { + /* Bind failed, and set the error code. Bummer */ + cl->client->errorValue = cx->id; + *error = __glXBadContextState; + return 0; + } + } + __glXLastContext = cx; + return cx; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** If we're expecting a glXRenderLarge request, this better be one. + */ + if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) { + client->errorValue = stuff->glxCode; + return __glXBadLargeRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +static int __glXSwapDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.NX.original new file mode 100644 index 000000000..fe2f4aa6c --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.NX.original @@ -0,0 +1,550 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglxext.c" + +#else + +/* $XFree86: xc/programs/Xserver/GL/glx/glxext.c,v 1.8 2001/08/23 18:25:40 alanh Exp $ +** The contents of this file are subject to the GLX Public License Version 1.0 +** (the "License"). You may not use this file except in compliance with the +** License. You may obtain a copy of the License at Silicon Graphics, Inc., +** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +** or at http://www.sgi.com/software/opensource/glx/license.html. +** +** Software distributed under the License is distributed on an "AS IS" +** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY +** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR +** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific +** language governing rights and limitations under the License. +** +** The Original Software is GLX version 1.2 source code, released February, +** 1999. The developer of the Original Software is Silicon Graphics, Inc. +** Those portions of the Subject Software created by Silicon Graphics, Inc. +** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. +** +*/ + +#define NEED_REPLIES +#include "glxserver.h" +#include +#include +#include +#include "g_disptab.h" +#include "unpack.h" +#include "glxutil.h" +#include "glxext.h" +#include "micmap.h" + +#include "Trap.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +extern __GLXextensionInfo __glDDXExtensionInfo; + +__GLXextensionInfo *__glXExt = &__glDDXExtensionInfo; + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + (*__glXExt->resetExtension)(); + __glXScreenReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + + if (cl->returnBuf) __glXFree(cl->returnBuf); + if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); + if (cl->currentContexts) __glXFree(cl->currentContexts); + __glXMemset(cl, 0, sizeof(__GLXclientState)); + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + +} + +/* +** Reset state used to keep track of large (multi-request) commands. +*/ +void __glXResetLargeCommandStatus(__GLXclientState *cl) +{ + cl->largeCmdBytesSoFar = 0; + cl->largeCmdBytesTotal = 0; + cl->largeCmdRequestsSoFar = 0; + cl->largeCmdRequestsTotal = 0; +} + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + __glXDeassociateContext(cx, cx->glxPriv); + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + pGlxPixmap->idExists = False; + if (!pGlxPixmap->refcnt) { + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + __glXFree(pGlxPixmap); + } + + return True; +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + if (!cx->isDirect) { + if ((*cx->gc->exports.destroyContext)((__GLcontext *)cx->gc) == GL_FALSE) { + return GL_FALSE; + } + } + if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); + if (cx->selectBuf) __glXFree(cx->selectBuf); + __glXFree(cx); + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +/************************************************************************/ + +/* +** These routines can be used to check whether a particular GL command +** has caused an error. Specifically, we use them to check whether a +** given query has caused an error, in which case a zero-length data +** reply is sent to the client. +*/ + +static GLboolean errorOccured = GL_FALSE; + +/* +** The GL was will call this routine if an error occurs. +*/ +void __glXErrorCallBack(__GLinterface *gc, GLenum code) +{ + errorOccured = GL_TRUE; +} + +/* +** Clear the error flag before calling the GL command. +*/ +void __glXClearErrorOccured(void) +{ + errorOccured = GL_FALSE; +} + +/* +** Check if the GL command caused an error. +*/ +GLboolean __glXErrorOccured(void) +{ + return errorOccured; +} + +/************************************************************************/ + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef X11R5 + __glXContextRes = CreateNewResourceType(ContextGone); + __glXClientRes = CreateNewResourceType(ClientGone); + __glXPixmapRes = CreateNewResourceType(PixmapGone); +#else + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone); +#endif + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return __glXExt->type; +} + +/************************************************************************/ + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + (*__glXExt->setVisualConfigs)(nconfigs, configs, privates); +} + +static miInitVisualsProcPtr saveInitVisualsProc; + +Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, + int *nvisualp, int *ndepthp, + int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, + int preferredVis) +{ + Bool ret; + + if (saveInitVisualsProc) { + ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, + rootDepthp, defaultVisp, sizes, bitsPerRGB, + preferredVis); + if (!ret) + return False; + } + (*__glXExt->initVisuals)(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB); + return True; +} + +void +GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) +{ + saveInitVisualsProc = *initVisProc; + *initVisProc = GlxInitVisuals; +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/* +** Make a context the current one for the GL (in this implementation, there +** is only one instance of the GL, and we use it to serve all GL clients by +** switching it between different contexts). While we are at it, look up +** a context by its tag and return its (__GLXcontext *). +*/ +__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, + int *error) +{ + __GLXcontext *cx; + + /* + ** See if the context tag is legal; it is managed by the extension, + ** so if it's invalid, we have an implementation error. + */ + cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag); + if (!cx) { + cl->client->errorValue = tag; + *error = __glXBadContextTag; + return 0; + } + + if (!cx->isDirect) { + if (cx->glxPriv == NULL) { + /* + ** The drawable has vanished. It must be a window, because only + ** windows can be destroyed from under us; GLX pixmaps are + ** refcounted and don't go away until no one is using them. + */ + *error = __glXBadCurrentWindow; + return 0; + } + } + + if (cx == __glXLastContext) { + /* No need to re-bind */ + return cx; + } + + /* Make this context the current one for the GL. */ + if (!cx->isDirect) { + if (!(*cx->gc->exports.forceCurrent)((__GLcontext *)cx->gc)) { + /* Bind failed, and set the error code. Bummer */ + cl->client->errorValue = cx->id; + *error = __glXBadContextState; + return 0; + } + } + __glXLastContext = cx; + return cx; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** If we're expecting a glXRenderLarge request, this better be one. + */ + if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) { + client->errorValue = stuff->glxCode; + return __glXBadLargeRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +static int __glXSwapDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.XF86.original new file mode 100644 index 000000000..95a9c2e6e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.XF86.original @@ -0,0 +1,489 @@ +/* $XFree86: xc/programs/Xserver/GL/glx/glxext.c,v 1.8 2001/08/23 18:25:40 alanh Exp $ +** The contents of this file are subject to the GLX Public License Version 1.0 +** (the "License"). You may not use this file except in compliance with the +** License. You may obtain a copy of the License at Silicon Graphics, Inc., +** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +** or at http://www.sgi.com/software/opensource/glx/license.html. +** +** Software distributed under the License is distributed on an "AS IS" +** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY +** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR +** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific +** language governing rights and limitations under the License. +** +** The Original Software is GLX version 1.2 source code, released February, +** 1999. The developer of the Original Software is Silicon Graphics, Inc. +** Those portions of the Subject Software created by Silicon Graphics, Inc. +** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. +** +*/ + +#define NEED_REPLIES +#include "glxserver.h" +#include +#include +#include +#include "g_disptab.h" +#include "unpack.h" +#include "glxutil.h" +#include "glxext.h" +#include "micmap.h" + + +extern __GLXextensionInfo __glDDXExtensionInfo; + +__GLXextensionInfo *__glXExt = &__glDDXExtensionInfo; + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + (*__glXExt->resetExtension)(); + __glXScreenReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + + if (cl->returnBuf) __glXFree(cl->returnBuf); + if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); + if (cl->currentContexts) __glXFree(cl->currentContexts); + __glXMemset(cl, 0, sizeof(__GLXclientState)); + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + +} + +/* +** Reset state used to keep track of large (multi-request) commands. +*/ +void __glXResetLargeCommandStatus(__GLXclientState *cl) +{ + cl->largeCmdBytesSoFar = 0; + cl->largeCmdBytesTotal = 0; + cl->largeCmdRequestsSoFar = 0; + cl->largeCmdRequestsTotal = 0; +} + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + __glXDeassociateContext(cx, cx->glxPriv); + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + pGlxPixmap->idExists = False; + if (!pGlxPixmap->refcnt) { + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + __glXFree(pGlxPixmap); + } + + return True; +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + if (!cx->isDirect) { + if ((*cx->gc->exports.destroyContext)((__GLcontext *)cx->gc) == GL_FALSE) { + return GL_FALSE; + } + } + if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); + if (cx->selectBuf) __glXFree(cx->selectBuf); + __glXFree(cx); + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +/************************************************************************/ + +/* +** These routines can be used to check whether a particular GL command +** has caused an error. Specifically, we use them to check whether a +** given query has caused an error, in which case a zero-length data +** reply is sent to the client. +*/ + +static GLboolean errorOccured = GL_FALSE; + +/* +** The GL was will call this routine if an error occurs. +*/ +void __glXErrorCallBack(__GLinterface *gc, GLenum code) +{ + errorOccured = GL_TRUE; +} + +/* +** Clear the error flag before calling the GL command. +*/ +void __glXClearErrorOccured(void) +{ + errorOccured = GL_FALSE; +} + +/* +** Check if the GL command caused an error. +*/ +GLboolean __glXErrorOccured(void) +{ + return errorOccured; +} + +/************************************************************************/ + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef X11R5 + __glXContextRes = CreateNewResourceType(ContextGone); + __glXClientRes = CreateNewResourceType(ClientGone); + __glXPixmapRes = CreateNewResourceType(PixmapGone); +#else + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone); +#endif + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return __glXExt->type; +} + +/************************************************************************/ + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + (*__glXExt->setVisualConfigs)(nconfigs, configs, privates); +} + +static miInitVisualsProcPtr saveInitVisualsProc; + +Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, + int *nvisualp, int *ndepthp, + int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, + int preferredVis) +{ + Bool ret; + + if (saveInitVisualsProc) { + ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, + rootDepthp, defaultVisp, sizes, bitsPerRGB, + preferredVis); + if (!ret) + return False; + } + (*__glXExt->initVisuals)(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB); + return True; +} + +void +GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) +{ + saveInitVisualsProc = *initVisProc; + *initVisProc = GlxInitVisuals; +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/* +** Make a context the current one for the GL (in this implementation, there +** is only one instance of the GL, and we use it to serve all GL clients by +** switching it between different contexts). While we are at it, look up +** a context by its tag and return its (__GLXcontext *). +*/ +__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, + int *error) +{ + __GLXcontext *cx; + + /* + ** See if the context tag is legal; it is managed by the extension, + ** so if it's invalid, we have an implementation error. + */ + cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag); + if (!cx) { + cl->client->errorValue = tag; + *error = __glXBadContextTag; + return 0; + } + + if (!cx->isDirect) { + if (cx->glxPriv == NULL) { + /* + ** The drawable has vanished. It must be a window, because only + ** windows can be destroyed from under us; GLX pixmaps are + ** refcounted and don't go away until no one is using them. + */ + *error = __glXBadCurrentWindow; + return 0; + } + } + + if (cx == __glXLastContext) { + /* No need to re-bind */ + return cx; + } + + /* Make this context the current one for the GL. */ + if (!cx->isDirect) { + if (!(*cx->gc->exports.forceCurrent)((__GLcontext *)cx->gc)) { + /* Bind failed, and set the error code. Bummer */ + cl->client->errorValue = cx->id; + *error = __glXBadContextState; + return 0; + } + } + __glXLastContext = cx; + return cx; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** If we're expecting a glXRenderLarge request, this better be one. + */ + if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) { + client->errorValue = stuff->glxCode; + return __glXBadLargeRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +static int __glXSwapDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c new file mode 100644 index 000000000..dfd82b76b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c @@ -0,0 +1,511 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglyph.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.6 2001/10/28 03:34:19 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" + +#ifdef NXAGENT_SERVER + +#include "NXpicturestr.h" +#include "NXglyphstr.h" +#include "Render.h" + +#define PANIC +#define WARNING +#undef DEBUG +#undef TEST + +#endif + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 } +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +Bool +GlyphInit (ScreenPtr pScreen) +{ + return TRUE; +} + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) + { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) + { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) + { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || + memcmp (&compare->info, &glyph->info, compare->size) == 0)) + { + break; + } + if (!step) + { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +CARD32 +HashGlyph (GlyphPtr glyph) +{ + CARD32 *bits = (CARD32 *) &(glyph->info); + CARD32 hash; + int n = glyph->size / sizeof (CARD32); + + hash = 0; + while (n--) + hash ^= *bits++; + return hash; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef (GlyphPtr glyph, char *where) +{ + ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates (GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) + { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef (g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +void +FreeGlyph (GlyphPtr glyph, int format) +{ + CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) + { + GlyphRefPtr gr; + int i; + int first; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) + { + if (first != -1) + DuplicateRef (glyph, "FreeGlyph check"); + first = i; + } + + gr = FindGlyphRef (&globalGlyphs[format], + HashGlyph (glyph), TRUE, glyph); + if (gr - globalGlyphs[format].table != first) + DuplicateRef (glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + xfree (glyph); + } +} + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 hash; + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + hash = HashGlyph (glyph); + gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + xfree (glyph); + glyph = gr->glyph; + } + else + { + gr->glyph = glyph; + gr->signature = hash; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph (gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = 1; + + #endif + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph (glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +#ifdef NXAGENT_SERVER + +GlyphPtr FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr -> glyph; + + if (glyph == DeletedGlyph) + { + glyph = 0; + } + else if (gr -> corruptedGlyph == 1) + { + #ifdef DEBUG + fprintf(stderr, "FindGlyphRef: Going to synchronize the glyph [%p] for glyphset [%p].\n", + (void *) glyph, (void *) glyphSet); + #endif + + nxagentAddGlyphs(glyphSet, &id, &(glyph -> info), 1, + (CARD8*)(glyph + 1), glyph -> size - sizeof(xGlyphInfo)); + } + + return glyph; +} + +#else + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +#endif + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int fdepth) +{ + int size; + GlyphPtr glyph; + + size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); + glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof (xGlyphInfo); + glyph->info = *gi; + return glyph; +} + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); + if (!hash->table) + return FALSE; + memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + #ifdef NXAGENT_SERVER + + CARD32 c; + + #endif + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet (tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash (&newHash, hashSet)) + return FALSE; + if (hash->table) + { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) + { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) + { + s = hash->table[i].signature; + + #ifdef NXAGENT_SERVER + + c = hash->table[i].corruptedGlyph; + + #endif + + gr = FindGlyphRef (&newHash, s, global, glyph); + gr->signature = s; + gr->glyph = glyph; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = c; + + #endif + + ++newHash.tableEntries; + } + } + xfree (hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + + if (!globalGlyphs[fdepth].hashSet) + { + if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + glyphSet = xalloc (sizeof (GlyphSetRec)); + if (!glyphSet) + return FALSE; + if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) + { + xfree (glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet (pointer value, + XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) + { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) + { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph (glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) + { + xfree (globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); + xfree (table); + xfree (glyphSet); + } + return Success; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.NX.original new file mode 100644 index 000000000..dfd82b76b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.NX.original @@ -0,0 +1,511 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglyph.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.6 2001/10/28 03:34:19 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" + +#ifdef NXAGENT_SERVER + +#include "NXpicturestr.h" +#include "NXglyphstr.h" +#include "Render.h" + +#define PANIC +#define WARNING +#undef DEBUG +#undef TEST + +#endif + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 } +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +Bool +GlyphInit (ScreenPtr pScreen) +{ + return TRUE; +} + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) + { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) + { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) + { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || + memcmp (&compare->info, &glyph->info, compare->size) == 0)) + { + break; + } + if (!step) + { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +CARD32 +HashGlyph (GlyphPtr glyph) +{ + CARD32 *bits = (CARD32 *) &(glyph->info); + CARD32 hash; + int n = glyph->size / sizeof (CARD32); + + hash = 0; + while (n--) + hash ^= *bits++; + return hash; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef (GlyphPtr glyph, char *where) +{ + ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates (GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) + { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef (g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +void +FreeGlyph (GlyphPtr glyph, int format) +{ + CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) + { + GlyphRefPtr gr; + int i; + int first; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) + { + if (first != -1) + DuplicateRef (glyph, "FreeGlyph check"); + first = i; + } + + gr = FindGlyphRef (&globalGlyphs[format], + HashGlyph (glyph), TRUE, glyph); + if (gr - globalGlyphs[format].table != first) + DuplicateRef (glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + xfree (glyph); + } +} + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 hash; + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + hash = HashGlyph (glyph); + gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + xfree (glyph); + glyph = gr->glyph; + } + else + { + gr->glyph = glyph; + gr->signature = hash; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph (gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = 1; + + #endif + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph (glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +#ifdef NXAGENT_SERVER + +GlyphPtr FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr -> glyph; + + if (glyph == DeletedGlyph) + { + glyph = 0; + } + else if (gr -> corruptedGlyph == 1) + { + #ifdef DEBUG + fprintf(stderr, "FindGlyphRef: Going to synchronize the glyph [%p] for glyphset [%p].\n", + (void *) glyph, (void *) glyphSet); + #endif + + nxagentAddGlyphs(glyphSet, &id, &(glyph -> info), 1, + (CARD8*)(glyph + 1), glyph -> size - sizeof(xGlyphInfo)); + } + + return glyph; +} + +#else + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +#endif + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int fdepth) +{ + int size; + GlyphPtr glyph; + + size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); + glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof (xGlyphInfo); + glyph->info = *gi; + return glyph; +} + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); + if (!hash->table) + return FALSE; + memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + #ifdef NXAGENT_SERVER + + CARD32 c; + + #endif + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet (tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash (&newHash, hashSet)) + return FALSE; + if (hash->table) + { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) + { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) + { + s = hash->table[i].signature; + + #ifdef NXAGENT_SERVER + + c = hash->table[i].corruptedGlyph; + + #endif + + gr = FindGlyphRef (&newHash, s, global, glyph); + gr->signature = s; + gr->glyph = glyph; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = c; + + #endif + + ++newHash.tableEntries; + } + } + xfree (hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + + if (!globalGlyphs[fdepth].hashSet) + { + if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + glyphSet = xalloc (sizeof (GlyphSetRec)); + if (!glyphSet) + return FALSE; + if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) + { + xfree (glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet (pointer value, + XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) + { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) + { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph (glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) + { + xfree (globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); + xfree (table); + xfree (glyphSet); + } + return Success; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.XF86.original new file mode 100644 index 000000000..b4f08c223 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.XF86.original @@ -0,0 +1,416 @@ +/* + * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.6 2001/10/28 03:34:19 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" +#include "glyphstr.h" + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 } +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +Bool +GlyphInit (ScreenPtr pScreen) +{ + return TRUE; +} + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) + { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) + { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) + { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || + memcmp (&compare->info, &glyph->info, compare->size) == 0)) + { + break; + } + if (!step) + { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +CARD32 +HashGlyph (GlyphPtr glyph) +{ + CARD32 *bits = (CARD32 *) &(glyph->info); + CARD32 hash; + int n = glyph->size / sizeof (CARD32); + + hash = 0; + while (n--) + hash ^= *bits++; + return hash; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef (GlyphPtr glyph, char *where) +{ + ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates (GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) + { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef (g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +void +FreeGlyph (GlyphPtr glyph, int format) +{ + CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) + { + GlyphRefPtr gr; + int i; + int first; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) + { + if (first != -1) + DuplicateRef (glyph, "FreeGlyph check"); + first = i; + } + + gr = FindGlyphRef (&globalGlyphs[format], + HashGlyph (glyph), TRUE, glyph); + if (gr - globalGlyphs[format].table != first) + DuplicateRef (glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + xfree (glyph); + } +} + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 hash; + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + hash = HashGlyph (glyph); + gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + xfree (glyph); + glyph = gr->glyph; + } + else + { + gr->glyph = glyph; + gr->signature = hash; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph (gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph (glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int fdepth) +{ + int size; + GlyphPtr glyph; + + size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); + glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof (xGlyphInfo); + glyph->info = *gi; + return glyph; +} + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); + if (!hash->table) + return FALSE; + memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet (tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash (&newHash, hashSet)) + return FALSE; + if (hash->table) + { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) + { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) + { + s = hash->table[i].signature; + gr = FindGlyphRef (&newHash, s, global, glyph); + gr->signature = s; + gr->glyph = glyph; + ++newHash.tableEntries; + } + } + xfree (hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + + if (!globalGlyphs[fdepth].hashSet) + { + if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + glyphSet = xalloc (sizeof (GlyphSetRec)); + if (!glyphSet) + return FALSE; + if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) + { + xfree (glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet (pointer value, + XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) + { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) + { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph (glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) + { + xfree (globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); + xfree (table); + xfree (glyphSet); + } + return Success; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c new file mode 100644 index 000000000..599e4c616 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c @@ -0,0 +1,252 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglyphcurs.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: glyphcurs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "misc.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + +#include "../../fb/fb.h" +#include "Pixmaps.h" + +#ifndef True +#define True 1 +#endif + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(pfont, ch, cm, ppbits) + FontPtr pfont; + unsigned int ch; + register CursorMetricPtr cm; + unsigned char **ppbits; +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = fbCreatePixmap(pScreen, cm->width, cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + fbDestroyPixmap(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Created virtual pixmap at [%p] with width [%d] height [%d] depth [%d].\n", + (void *) ppix, cm->width, cm->height, 1); + #endif + + nxagentPixmapPriv(ppix) -> id = 0; + nxagentPixmapPriv(ppix) -> mid = 0; + nxagentPixmapPriv(ppix) -> isVirtual = True; + nxagentPixmapPriv(ppix) -> pRealPixmap = NULL; + nxagentPixmapPriv(ppix) -> pVirtualPixmap = NULL; + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + pGC->stateChanges |= GCFunction | GCForeground | GCFont; + pGC->alu = GXcopy; + + pGC->fgPixel = 0; + + pfont->refcnt++; + + if (pGC->font) + CloseFont(pGC->font, (Font)0); + + pGC->font = pfont; + + ValidateGC((DrawablePtr)ppix, pGC); + fbPolyFillRect((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + pGC->fgPixel = 1; + + pGC->stateChanges |= GCForeground; + + ValidateGC((DrawablePtr)ppix, pGC); + miPolyText16((DrawablePtr)ppix, pGC, (int)cm->xhot, (int)cm->yhot, (int)1, (unsigned short*)char2b); + fbGetImage((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + fbDestroyPixmap(ppix); + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Destroyed virtual pixmap at [%p].\n", + (void *) ppix); + #endif + + return Success; +} + + +Bool +CursorMetricsFromGlyph( pfont, ch, cm) + register FontPtr pfont; + unsigned ch; + register CursorMetricPtr cm; +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.NX.original new file mode 100644 index 000000000..599e4c616 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.NX.original @@ -0,0 +1,252 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglyphcurs.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: glyphcurs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "misc.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + +#include "../../fb/fb.h" +#include "Pixmaps.h" + +#ifndef True +#define True 1 +#endif + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(pfont, ch, cm, ppbits) + FontPtr pfont; + unsigned int ch; + register CursorMetricPtr cm; + unsigned char **ppbits; +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = fbCreatePixmap(pScreen, cm->width, cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + fbDestroyPixmap(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Created virtual pixmap at [%p] with width [%d] height [%d] depth [%d].\n", + (void *) ppix, cm->width, cm->height, 1); + #endif + + nxagentPixmapPriv(ppix) -> id = 0; + nxagentPixmapPriv(ppix) -> mid = 0; + nxagentPixmapPriv(ppix) -> isVirtual = True; + nxagentPixmapPriv(ppix) -> pRealPixmap = NULL; + nxagentPixmapPriv(ppix) -> pVirtualPixmap = NULL; + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + pGC->stateChanges |= GCFunction | GCForeground | GCFont; + pGC->alu = GXcopy; + + pGC->fgPixel = 0; + + pfont->refcnt++; + + if (pGC->font) + CloseFont(pGC->font, (Font)0); + + pGC->font = pfont; + + ValidateGC((DrawablePtr)ppix, pGC); + fbPolyFillRect((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + pGC->fgPixel = 1; + + pGC->stateChanges |= GCForeground; + + ValidateGC((DrawablePtr)ppix, pGC); + miPolyText16((DrawablePtr)ppix, pGC, (int)cm->xhot, (int)cm->yhot, (int)1, (unsigned short*)char2b); + fbGetImage((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + fbDestroyPixmap(ppix); + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Destroyed virtual pixmap at [%p].\n", + (void *) ppix); + #endif + + return Success; +} + + +Bool +CursorMetricsFromGlyph( pfont, ch, cm) + register FontPtr pfont; + unsigned ch; + register CursorMetricPtr cm; +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.XF86.original new file mode 100644 index 000000000..630e98fa3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.XF86.original @@ -0,0 +1,197 @@ +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: glyphcurs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "misc.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(pfont, ch, cm, ppbits) + FontPtr pfont; + unsigned int ch; + register CursorMetricPtr cm; + unsigned char **ppbits; +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = (PixmapPtr)(*pScreen->CreatePixmap)(pScreen, cm->width, + cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + (*pScreen->DestroyPixmap)(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + /* fill the pixmap with 0 */ + gcval[0].val = GXcopy; + gcval[1].val = 0; + gcval[2].ptr = (pointer)pfont; + dixChangeGC(NullClient, pGC, GCFunction | GCForeground | GCFont, + NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyFillRect)((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + dixChangeGC(NullClient, pGC, GCForeground, NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyText16)((DrawablePtr)ppix, pGC, cm->xhot, cm->yhot, + 1, (unsigned short *)char2b); + (*pScreen->GetImage)((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + (*pScreen->DestroyPixmap)(ppix); + return Success; +} + + +Bool +CursorMetricsFromGlyph( pfont, ch, cm) + register FontPtr pfont; + unsigned ch; + register CursorMetricPtr cm; +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h new file mode 100644 index 000000000..970d0bb4d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h @@ -0,0 +1,161 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglyphstr.h" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.4 2001/01/21 21:19:39 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original glyphstr.h + * or symbols will be redefined. The code here adds a field + * to _GlyphSet. This should be done by defining a new type + * and casting when appropriate. + */ + +#ifndef _GLYPHSTR_H_ +#define _GLYPHSTR_H_ + +#include "renderproto.h" +#include "../../render/picture.h" +#include "screenint.h" + +#define GlyphFormat1 0 +#define GlyphFormat4 1 +#define GlyphFormat8 2 +#define GlyphFormat16 3 +#define GlyphFormat32 4 +#define GlyphFormatNum 5 + +typedef struct _Glyph { + CARD32 refcnt; + CARD32 size; /* info + bitmap */ + xGlyphInfo info; + /* bits follow */ +} GlyphRec, *GlyphPtr; + +typedef struct _GlyphRef { + CARD32 signature; + GlyphPtr glyph; + CARD16 corruptedGlyph; +} GlyphRefRec, *GlyphRefPtr; + +#define DeletedGlyph ((GlyphPtr) 1) + +typedef struct _GlyphHashSet { + CARD32 entries; + CARD32 size; + CARD32 rehash; +} GlyphHashSetRec, *GlyphHashSetPtr; + +typedef struct _GlyphHash { + GlyphRefPtr table; + GlyphHashSetPtr hashSet; + CARD32 tableEntries; +} GlyphHashRec, *GlyphHashPtr; + +typedef struct _GlyphSet { + CARD32 refcnt; + PictFormatPtr format; + int fdepth; + GlyphHashRec hash; + CARD32 remoteID; +} GlyphSetRec, *GlyphSetPtr; + +typedef struct _GlyphList { + INT16 xOff; + INT16 yOff; + CARD8 len; + PictFormatPtr format; +} GlyphListRec, *GlyphListPtr; + +extern GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled); + +Bool +GlyphInit (ScreenPtr pScreen); + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare); + +CARD32 +HashGlyph (GlyphPtr glyph); + +void +FreeGlyph (GlyphPtr glyph, int format); + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id); + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int format); + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet); + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global); + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change); + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format); + +int +FreeGlyphSet (pointer value, + XID gid); + + + +#endif /* _GLYPHSTR_H_ */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.NX.original new file mode 100644 index 000000000..970d0bb4d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.NX.original @@ -0,0 +1,161 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXglyphstr.h" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.4 2001/01/21 21:19:39 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original glyphstr.h + * or symbols will be redefined. The code here adds a field + * to _GlyphSet. This should be done by defining a new type + * and casting when appropriate. + */ + +#ifndef _GLYPHSTR_H_ +#define _GLYPHSTR_H_ + +#include "renderproto.h" +#include "../../render/picture.h" +#include "screenint.h" + +#define GlyphFormat1 0 +#define GlyphFormat4 1 +#define GlyphFormat8 2 +#define GlyphFormat16 3 +#define GlyphFormat32 4 +#define GlyphFormatNum 5 + +typedef struct _Glyph { + CARD32 refcnt; + CARD32 size; /* info + bitmap */ + xGlyphInfo info; + /* bits follow */ +} GlyphRec, *GlyphPtr; + +typedef struct _GlyphRef { + CARD32 signature; + GlyphPtr glyph; + CARD16 corruptedGlyph; +} GlyphRefRec, *GlyphRefPtr; + +#define DeletedGlyph ((GlyphPtr) 1) + +typedef struct _GlyphHashSet { + CARD32 entries; + CARD32 size; + CARD32 rehash; +} GlyphHashSetRec, *GlyphHashSetPtr; + +typedef struct _GlyphHash { + GlyphRefPtr table; + GlyphHashSetPtr hashSet; + CARD32 tableEntries; +} GlyphHashRec, *GlyphHashPtr; + +typedef struct _GlyphSet { + CARD32 refcnt; + PictFormatPtr format; + int fdepth; + GlyphHashRec hash; + CARD32 remoteID; +} GlyphSetRec, *GlyphSetPtr; + +typedef struct _GlyphList { + INT16 xOff; + INT16 yOff; + CARD8 len; + PictFormatPtr format; +} GlyphListRec, *GlyphListPtr; + +extern GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled); + +Bool +GlyphInit (ScreenPtr pScreen); + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare); + +CARD32 +HashGlyph (GlyphPtr glyph); + +void +FreeGlyph (GlyphPtr glyph, int format); + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id); + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int format); + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet); + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global); + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change); + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format); + +int +FreeGlyphSet (pointer value, + XID gid); + + + +#endif /* _GLYPHSTR_H_ */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.XF86.original new file mode 100644 index 000000000..99f55e3eb --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.XF86.original @@ -0,0 +1,127 @@ +/* + * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.4 2001/01/21 21:19:39 tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _GLYPHSTR_H_ +#define _GLYPHSTR_H_ + +#include "renderproto.h" +#include "picture.h" +#include "screenint.h" + +#define GlyphFormat1 0 +#define GlyphFormat4 1 +#define GlyphFormat8 2 +#define GlyphFormat16 3 +#define GlyphFormat32 4 +#define GlyphFormatNum 5 + +typedef struct _Glyph { + CARD32 refcnt; + CARD32 size; /* info + bitmap */ + xGlyphInfo info; + /* bits follow */ +} GlyphRec, *GlyphPtr; + +typedef struct _GlyphRef { + CARD32 signature; + GlyphPtr glyph; +} GlyphRefRec, *GlyphRefPtr; + +#define DeletedGlyph ((GlyphPtr) 1) + +typedef struct _GlyphHashSet { + CARD32 entries; + CARD32 size; + CARD32 rehash; +} GlyphHashSetRec, *GlyphHashSetPtr; + +typedef struct _GlyphHash { + GlyphRefPtr table; + GlyphHashSetPtr hashSet; + CARD32 tableEntries; +} GlyphHashRec, *GlyphHashPtr; + +typedef struct _GlyphSet { + CARD32 refcnt; + PictFormatPtr format; + int fdepth; + GlyphHashRec hash; +} GlyphSetRec, *GlyphSetPtr; + +typedef struct _GlyphList { + INT16 xOff; + INT16 yOff; + CARD8 len; + PictFormatPtr format; +} GlyphListRec, *GlyphListPtr; + +extern GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled); + +Bool +GlyphInit (ScreenPtr pScreen); + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare); + +CARD32 +HashGlyph (GlyphPtr glyph); + +void +FreeGlyph (GlyphPtr glyph, int format); + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id); + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int format); + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet); + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global); + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change); + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format); + +int +FreeGlyphSet (pointer value, + XID gid); + + + +#endif /* _GLYPHSTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c new file mode 100644 index 000000000..bd068170c --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c @@ -0,0 +1,938 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmiexpose.c" + +#else + +/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9 2001/12/14 20:00:22 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "Xprotostr.h" + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include "Xmd.h" + +#include "globals.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifdef NXAGENT_SERVER + +#include "Windows.h" + +#endif + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + expBox.x1 = 0; + expBox.y1 = 0; + expBox.x2 = 0; + expBox.y2 = 0; + +#endif + + /* This prevents warning about pscr not being used. */ + pGC->pScreen = pscr = pGC->pScreen; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, NullBox, 0); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, NullBox, 0); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + int scrnum = pWin->drawable.pScreen->myNum; + int x = 0, y = 0; + XID realWin = 0; + + if(!pWin->parent) { + x = panoramiXdataPtr[scrnum].x; + y = panoramiXdataPtr[scrnum].y; + pWin = WindowTable[0]; + realWin = pWin->drawable.id; + } else if (scrnum) { + PanoramiXRes *win; + win = PanoramiXFindIDByScrnum(XRT_WINDOW, + pWin->drawable.id, scrnum); + if(!win) { + DEALLOCATE_LOCAL(pEvent); + return; + } + realWin = win->info[0].id; + pWin = LookupIDByType(realWin, RT_WINDOW); + } + if(x || y || scrnum) + for (i = 0; i < numRects; i++) { + pEvent[i].u.expose.window = realWin; + pEvent[i].u.expose.x += x; + pEvent[i].u.expose.y += y; + } + } +#endif + + DeliverEvents(pWin, pEvent, numRects, NullWindow); + + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ +#ifdef NXAGENT_SERVER + + int total; + +#endif + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } +#ifdef NXAGENT_SERVER + + /* + * If the number of rectangles is greater + * than 4, let the function decide. + */ + + total = REGION_NUM_RECTS(exposures); + + if (clientInterested && exposures && (total > RECTLIMIT || + (total > 4 && nxagentExtentsPredicate(total) == 1))) +#else + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) +#endif + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC ( + pointer value, + XID id) +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; + + return 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + prgnWin.extents.x1 = 0; + prgnWin.extents.y1 = 0; + prgnWin.extents.x2 = 0; + prgnWin.extents.y2 = 0; + + prgnWin.data = NULL; + + oldCorner.x = 0; + oldCorner.y = 0; + +#endif + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +void +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +} + +#endif /* NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.NX.original new file mode 100644 index 000000000..bd068170c --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.NX.original @@ -0,0 +1,938 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmiexpose.c" + +#else + +/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9 2001/12/14 20:00:22 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "Xprotostr.h" + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include "Xmd.h" + +#include "globals.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifdef NXAGENT_SERVER + +#include "Windows.h" + +#endif + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + expBox.x1 = 0; + expBox.y1 = 0; + expBox.x2 = 0; + expBox.y2 = 0; + +#endif + + /* This prevents warning about pscr not being used. */ + pGC->pScreen = pscr = pGC->pScreen; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, NullBox, 0); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, NullBox, 0); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + int scrnum = pWin->drawable.pScreen->myNum; + int x = 0, y = 0; + XID realWin = 0; + + if(!pWin->parent) { + x = panoramiXdataPtr[scrnum].x; + y = panoramiXdataPtr[scrnum].y; + pWin = WindowTable[0]; + realWin = pWin->drawable.id; + } else if (scrnum) { + PanoramiXRes *win; + win = PanoramiXFindIDByScrnum(XRT_WINDOW, + pWin->drawable.id, scrnum); + if(!win) { + DEALLOCATE_LOCAL(pEvent); + return; + } + realWin = win->info[0].id; + pWin = LookupIDByType(realWin, RT_WINDOW); + } + if(x || y || scrnum) + for (i = 0; i < numRects; i++) { + pEvent[i].u.expose.window = realWin; + pEvent[i].u.expose.x += x; + pEvent[i].u.expose.y += y; + } + } +#endif + + DeliverEvents(pWin, pEvent, numRects, NullWindow); + + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ +#ifdef NXAGENT_SERVER + + int total; + +#endif + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } +#ifdef NXAGENT_SERVER + + /* + * If the number of rectangles is greater + * than 4, let the function decide. + */ + + total = REGION_NUM_RECTS(exposures); + + if (clientInterested && exposures && (total > RECTLIMIT || + (total > 4 && nxagentExtentsPredicate(total) == 1))) +#else + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) +#endif + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC ( + pointer value, + XID id) +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; + + return 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + prgnWin.extents.x1 = 0; + prgnWin.extents.y1 = 0; + prgnWin.extents.x2 = 0; + prgnWin.extents.y2 = 0; + + prgnWin.data = NULL; + + oldCorner.x = 0; + oldCorner.y = 0; + +#endif + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +void +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +} + +#endif /* NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.XF86.original new file mode 100644 index 000000000..ca896b9e0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.XF86.original @@ -0,0 +1,873 @@ +/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9 2001/12/14 20:00:22 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "Xprotostr.h" + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include "Xmd.h" + +#include "globals.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + + /* This prevents warning about pscr not being used. */ + pGC->pScreen = pscr = pGC->pScreen; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, NullBox, 0); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, NullBox, 0); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + int scrnum = pWin->drawable.pScreen->myNum; + int x = 0, y = 0; + XID realWin = 0; + + if(!pWin->parent) { + x = panoramiXdataPtr[scrnum].x; + y = panoramiXdataPtr[scrnum].y; + pWin = WindowTable[0]; + realWin = pWin->drawable.id; + } else if (scrnum) { + PanoramiXRes *win; + win = PanoramiXFindIDByScrnum(XRT_WINDOW, + pWin->drawable.id, scrnum); + if(!win) { + DEALLOCATE_LOCAL(pEvent); + return; + } + realWin = win->info[0].id; + pWin = LookupIDByType(realWin, RT_WINDOW); + } + if(x || y || scrnum) + for (i = 0; i < numRects; i++) { + pEvent[i].u.expose.window = realWin; + pEvent[i].u.expose.x += x; + pEvent[i].u.expose.y += y; + } + } +#endif + + DeliverEvents(pWin, pEvent, numRects, NullWindow); + + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC ( + pointer value, + XID id) +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; + + return 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +void +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c b/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c new file mode 100644 index 000000000..2521ae5c7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c @@ -0,0 +1,322 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmiglyph.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.6 2000/12/05 03:13:31 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifdef NXAGENT_SERVER + +#include "Render.h" + +#endif + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + PixmapPtr pPixmap = 0; + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents; + CARD32 component_alpha; + + #ifdef NXAGENT_SERVER + + /* + * Get rid of the warning. + */ + + extents.x1 = 0; + extents.y1 = 0; + + #endif + + if (maskFormat) + { + GCPtr pGC; + xRectangle rect; + + #ifdef NXAGENT_SERVER + + if (nxagentGlyphsExtents != NullBox) + { + memcpy(&extents, nxagentGlyphsExtents, sizeof(BoxRec)); + } + else + { + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents (nlist, list, glyphs, &extents); + + memcpy(nxagentGlyphsExtents, &extents, sizeof(BoxRec)); + } + + #else + + miGlyphExtents (nlist, list, glyphs, &extents); + + #endif + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); + + if (!pMaskPixmap) + return; + + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture (0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + + if (!pMask) + { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); + ValidateGC (&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + x = -extents.x1; + y = -extents.y1; + } + else + { + pMask = pDst; + x = 0; + y = 0; + } + pPicture = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + + while (n--) + { + glyph = *glyphs++; + if (!pPicture) + { + pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, + list->format->depth, + list->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + component_alpha = NeedsComponent(list->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, list->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + + #ifdef NXAGENT_SERVER + + /* + * The following line fixes a problem with glyphs that appeared + * as clipped. It was a side effect due the validate function + * "ValidatePicture" that makes a check on the Drawable serial + * number instead of the picture serial number, failing thus + * the clip mask update. + */ + + pPicture->pDrawable->serialNumber = NEXT_SERIAL_NUMBER; + + #endif + + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (maskFormat) + { + CompositePicture (PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + else + { + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + + list++; + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + pPicture = 0; + pPixmap = 0; + } + } + if (maskFormat) + { + x = extents.x1; + y = extents.y1; + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + + FreePicture ((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } + +} + +#endif /* NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.NX.original new file mode 100644 index 000000000..2521ae5c7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.NX.original @@ -0,0 +1,322 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmiglyph.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.6 2000/12/05 03:13:31 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifdef NXAGENT_SERVER + +#include "Render.h" + +#endif + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + PixmapPtr pPixmap = 0; + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents; + CARD32 component_alpha; + + #ifdef NXAGENT_SERVER + + /* + * Get rid of the warning. + */ + + extents.x1 = 0; + extents.y1 = 0; + + #endif + + if (maskFormat) + { + GCPtr pGC; + xRectangle rect; + + #ifdef NXAGENT_SERVER + + if (nxagentGlyphsExtents != NullBox) + { + memcpy(&extents, nxagentGlyphsExtents, sizeof(BoxRec)); + } + else + { + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents (nlist, list, glyphs, &extents); + + memcpy(nxagentGlyphsExtents, &extents, sizeof(BoxRec)); + } + + #else + + miGlyphExtents (nlist, list, glyphs, &extents); + + #endif + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); + + if (!pMaskPixmap) + return; + + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture (0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + + if (!pMask) + { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); + ValidateGC (&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + x = -extents.x1; + y = -extents.y1; + } + else + { + pMask = pDst; + x = 0; + y = 0; + } + pPicture = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + + while (n--) + { + glyph = *glyphs++; + if (!pPicture) + { + pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, + list->format->depth, + list->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + component_alpha = NeedsComponent(list->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, list->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + + #ifdef NXAGENT_SERVER + + /* + * The following line fixes a problem with glyphs that appeared + * as clipped. It was a side effect due the validate function + * "ValidatePicture" that makes a check on the Drawable serial + * number instead of the picture serial number, failing thus + * the clip mask update. + */ + + pPicture->pDrawable->serialNumber = NEXT_SERIAL_NUMBER; + + #endif + + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (maskFormat) + { + CompositePicture (PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + else + { + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + + list++; + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + pPicture = 0; + pPixmap = 0; + } + } + if (maskFormat) + { + x = extents.x1; + y = extents.y1; + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + + FreePicture ((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } + +} + +#endif /* NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.XF86.original new file mode 100644 index 000000000..00b6764d6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.XF86.original @@ -0,0 +1,239 @@ +/* + * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.6 2000/12/05 03:13:31 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + PixmapPtr pPixmap = 0; + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents; + CARD32 component_alpha; + + if (maskFormat) + { + GCPtr pGC; + xRectangle rect; + + miGlyphExtents (nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); + if (!pMaskPixmap) + return; + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture (0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pMask) + { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); + ValidateGC (&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + x = -extents.x1; + y = -extents.y1; + } + else + { + pMask = pDst; + x = 0; + y = 0; + } + pPicture = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) + { + glyph = *glyphs++; + if (!pPicture) + { + pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, + list->format->depth, + list->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + component_alpha = NeedsComponent(list->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, list->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (maskFormat) + { + CompositePicture (PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + else + { + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + pPicture = 0; + pPixmap = 0; + } + } + if (maskFormat) + { + x = extents.x1; + y = extents.y1; + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + FreePicture ((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c new file mode 100644 index 000000000..7d0a99572 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c @@ -0,0 +1,204 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmitrap.c" + +#else + +/* + * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.9 2002/11/05 23:39:16 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) + { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC (&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +static xFixed +miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), + miLineFixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), + miLineFixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + } +} + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture = 0; + BoxRec bounds; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + if (maskFormat) + { + miTrapezoidBounds (ntrap, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + } + for (; ntrap; ntrap--, traps++) + { + if (!xTrapezoidValid(traps)) + continue; + if (!maskFormat) + { + miTrapezoidBounds (1, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + continue; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + continue; + } + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + if (!maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + } + if (maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } +} + +#endif /* NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.NX.original new file mode 100644 index 000000000..7d0a99572 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.NX.original @@ -0,0 +1,204 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmitrap.c" + +#else + +/* + * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.9 2002/11/05 23:39:16 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) + { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC (&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +static xFixed +miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), + miLineFixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), + miLineFixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + } +} + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture = 0; + BoxRec bounds; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + if (maskFormat) + { + miTrapezoidBounds (ntrap, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + } + for (; ntrap; ntrap--, traps++) + { + if (!xTrapezoidValid(traps)) + continue; + if (!maskFormat) + { + miTrapezoidBounds (1, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + continue; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + continue; + } + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + if (!maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + } + if (maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } +} + +#endif /* NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.XF86.original new file mode 100644 index 000000000..7f592ccd4 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.XF86.original @@ -0,0 +1,196 @@ +/* + * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.9 2002/11/05 23:39:16 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) + { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC (&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +static xFixed +miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), + miLineFixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), + miLineFixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + } +} + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture = 0; + BoxRec bounds; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + if (maskFormat) + { + miTrapezoidBounds (ntrap, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + } + for (; ntrap; ntrap--, traps++) + { + if (!xTrapezoidValid(traps)) + continue; + if (!maskFormat) + { + miTrapezoidBounds (1, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + continue; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + continue; + } + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + if (!maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + } + if (maskFormat) + { + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c b/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c new file mode 100644 index 000000000..ea2e7df28 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c @@ -0,0 +1,1205 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmiwindow.c" + +#else + +/* $XFree86: xc/programs/Xserver/mi/miwindow.c,v 1.7 2001/12/14 20:00:28 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: miwindow.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#include "X.h" +#include "miscstruct.h" +#include "region.h" +#include "mi.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" + +void +miClearToBackground(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x,y; + int w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + + /* compute everything using ints to avoid overflow */ + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + extents = &pWin->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pWin->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); + if (generateExposures) + (*pScreen->WindowExposures)(pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +/* + * For SaveUnders using backing-store. The idea is that when a window is mapped + * with saveUnder set TRUE, any windows it obscures will have its backing + * store turned on setting the DIXsaveUnder bit, + * The backing-store code must be written to allow for this + */ + +/*- + *----------------------------------------------------------------------- + * miCheckSubSaveUnder -- + * Check all the inferiors of a window for coverage by saveUnder + * windows. Called from ChangeSaveUnder and CheckSaveUnder. + * This code is very inefficient. + * + * Results: + * TRUE if any windows need to have backing-store removed. + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +static Bool +miCheckSubSaveUnder( + register WindowPtr pParent, /* Parent to check */ + WindowPtr pFirst, /* first reconfigured window */ + RegionPtr pRegion) /* Initial area obscured by saveUnder */ +{ + register WindowPtr pChild; /* Current child */ + register ScreenPtr pScreen; /* Screen to use */ + RegionRec SubRegion; /* Area of children obscured */ + Bool res = FALSE; /* result */ + Bool subInited=FALSE;/* SubRegion initialized */ + + pScreen = pParent->drawable.pScreen; + if ( (pChild = pParent->firstChild) ) + { + /* + * build region above first changed window + */ + + for (; pChild != pFirst; pChild = pChild->nextSib) + if (pChild->viewable && pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + + /* + * check region below and including first changed window + */ + + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + { + /* + * don't save under nephew/niece windows; + * use a separate region + */ + + if (pChild->firstChild) + { + if (!subInited) + { + REGION_INIT(pScreen, &SubRegion, NullBox, 0); + subInited = TRUE; + } + REGION_COPY(pScreen, &SubRegion, pRegion); + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + &SubRegion); + } + else + { + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + pRegion); + } + + if (pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + } + } + + if (subInited) + REGION_UNINIT(pScreen, &SubRegion); + } + + /* + * Check the state of this window. DIX save unders are + * enabled for viewable windows with some client expressing + * exposure interest and which intersect the save under region + */ + + if (pParent->viewable && + ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && + REGION_NOTEMPTY(pScreen, &pParent->borderSize) && + RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, + &pParent->borderSize)) != rgnOUT) + { + if (!pParent->DIXsaveUnder) + { + pParent->DIXsaveUnder = TRUE; + (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); + } + } + else + { + if (pParent->DIXsaveUnder) + { + res = TRUE; + pParent->DIXsaveUnder = FALSE; + } + } + return res; +} + + +/*- + *----------------------------------------------------------------------- + * miChangeSaveUnder -- + * Change the save-under state of a tree of windows. Called when + * a window with saveUnder TRUE is mapped/unmapped/reconfigured. + * + * Results: + * TRUE if any windows need to have backing-store removed (which + * means that PostChangeSaveUnder needs to be called later to + * finish the job). + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +Bool +miChangeSaveUnder(pWin, first) + register WindowPtr pWin; + WindowPtr first; /* First window to check. + * Used when pWin was restacked */ +{ + RegionRec rgn; /* Area obscured by saveUnder windows */ + register ScreenPtr pScreen; + Bool res; + + if (!deltaSaveUndersViewable && !numSaveUndersViewable) + return FALSE; + numSaveUndersViewable += deltaSaveUndersViewable; + deltaSaveUndersViewable = 0; + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, &rgn, NullBox, 1); + res = miCheckSubSaveUnder (pWin->parent, + pWin->saveUnder ? first : pWin->nextSib, + &rgn); + REGION_UNINIT(pScreen, &rgn); + return res; +} + +/*- + *----------------------------------------------------------------------- + * miPostChangeSaveUnder -- + * Actually turn backing-store off for those windows that no longer + * need to have it on. + * + * Results: + * None. + * + * Side Effects: + * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those + * windows affected. + * + *----------------------------------------------------------------------- + */ +void +miPostChangeSaveUnder(pWin, pFirst) + WindowPtr pWin; + WindowPtr pFirst; +{ + register WindowPtr pParent, pChild; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + if (!(pParent = pWin->parent)) + return; + ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; + if (!pParent->DIXsaveUnder && + (pParent->backingStore == NotUseful) && pParent->backStorage) + (*ChangeWindowAttributes)(pParent, CWBackingStore); + if (!(pChild = pFirst)) + return; + while (1) + { + if (!pChild->DIXsaveUnder && + (pChild->backingStore == NotUseful) && pChild->backStorage) + (*ChangeWindowAttributes)(pChild, CWBackingStore); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib) + { + pChild = pChild->parent; + if (pChild == pParent) + return; + } + pChild = pChild->nextSib; + } +} + +void +miMarkWindow(pWin) + register WindowPtr pWin; +{ + register ValidatePtr val; + + if (pWin->valdata) + return; + val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); + val->before.oldAbsCorner.x = pWin->drawable.x; + val->before.oldAbsCorner.y = pWin->drawable.y; + val->before.borderVisible = NullRegion; + val->before.resized = FALSE; + pWin->valdata = val; +} + +Bool +miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) + WindowPtr pWin; + WindowPtr pFirst; + WindowPtr *ppLayerWin; +{ + register BoxPtr box; + register WindowPtr pChild, pLast; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + + /* 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 ( (pChild = pFirst) ) + { + box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); + pLast = pChild->parent->lastChild; + while (1) + { + if (pChild->viewable) + { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) + { + (* MarkWindow)(pChild); + anyMarked = TRUE; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + } + while (!pChild->nextSib && (pChild != pLast)) + pChild = pChild->parent; + if (pChild == pLast) + break; + pChild = pChild->nextSib; + } + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + return anyMarked; +} + +/***** + * miHandleValidateExposures(pWin) + * starting at pWin, draw background in any windows that have exposure + * regions, translate the regions, restore any backing store, + * and then send any regions still exposed to the client + *****/ +void +miHandleValidateExposures(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + register ValidatePtr val; + ScreenPtr pScreen; + WindowExposuresProcPtr WindowExposures; + + pScreen = pWin->drawable.pScreen; + + pChild = pWin; + WindowExposures = pChild->drawable.pScreen->WindowExposures; + while (1) + { + if ( (val = pChild->valdata) ) + { + if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) + (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, + &val->after.borderExposed, + PW_BORDER); + REGION_UNINIT(pScreen, &val->after.borderExposed); + (*WindowExposures)(pChild, &val->after.exposed, NullRegion); + REGION_UNINIT(pScreen, &val->after.exposed); + xfree(val); + pChild->valdata = (ValidatePtr)NULL; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +void +miMoveWindow(pWin, x, y, pNextSib, kind) + register WindowPtr pWin; + int x,y; + WindowPtr pNextSib; + VTKind kind; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + short bw; + RegionPtr oldRegion = NULL; + DDXPointRec oldpt; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr windowToValidate; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return ; + pScreen = pWin->drawable.pScreen; + bw = wBorderWidth (pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) + { + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->borderClip); + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + } + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + SetWinSize (pWin); + SetBorderSize (pWin); + + (*pScreen->PositionWindow)(pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) + { + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, windowToValidate, (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, pLayerWin, (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); + (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); + REGION_DESTROY(pScreen, oldRegion); + /* XXX need to retile border if ParentRelative origin */ + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + + +/* + * pValid is a region of the screen which has been + * successfully copied -- recomputed exposed regions for affected windows + */ + +static int +miRecomputeExposures ( + register WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + register ScreenPtr pScreen; + RegionPtr pValid = (RegionPtr)value; + + if (pWin->valdata) + { + pScreen = pWin->drawable.pScreen; + /* + * compute exposed regions of this window + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->clipList, pValid); + /* + * compute exposed regions of the border + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid); + return WT_WALKCHILDREN; + } + return WT_NOMATCH; +} + +void +miSlideAndSizeWindow(pWin, x, y, w, h, pSib) + register WindowPtr pWin; + int x,y; + unsigned int w, h; + WindowPtr pSib; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + unsigned short width = pWin->drawable.width, + height = pWin->drawable.height; + short oldx = pWin->drawable.x, + oldy = pWin->drawable.y; + int bw = wBorderWidth (pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion = NULL; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr pFirstChange; + register WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + register unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion = NULL; + RegionPtr destClip; /* portions of destination already written */ + RegionPtr oldWinClip = NULL; /* old clip list for window */ + RegionPtr borderVisible = NullRegion; /* visible area of the border */ + RegionPtr bsExposed = NullRegion; /* backing store exposures */ + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return ; + + pScreen = pWin->drawable.pScreen; + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) + { + anyMarked = FALSE; + /* + * save the visible region of the window + */ + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->winSize); + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = (RegionPtr) NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + g = pChild->winGravity; + if (g != UnmapGravity) + { + if (!gravitate[g]) + gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); + REGION_UNION(pScreen, gravitate[g], + gravitate[g], &pChild->borderClip); + } + else + { + UnmapWindow(pChild, TRUE); + anyMarked = TRUE; + } + } + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + + oldWinClip = NULL; + if (pWin->bitGravity != ForgetGravity) + { + oldWinClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldWinClip, &pWin->clipList); + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder (pWin)) + { + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) + { + if (shrunk || moved) + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, + &pWin->winSize); + else + REGION_COPY(pScreen, borderVisible, + &pWin->borderClip); + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize (pWin); + SetBorderSize (pWin); + + dw = (int)w - (int)width; + dh = (int)h - (int)height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow)(pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + pRegion = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->backStorage) + REGION_COPY(pScreen, pRegion, &pWin->clipList); + + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + + if (pWin->valdata) + { + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); + } + + GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pRegion = &pWin->clipList; /* a convenient empty region */ + if (pWin->bitGravity == ForgetGravity) + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, NullRegion, oldx, oldy); + else + { + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, nx - x, ny - y, pRegion, oldx, oldy); + } + } + + if (WasViewable) + { + /* avoid the border */ + if (HasBorder (pWin)) + { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) + { + REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip) + { + /* + * clip to new clipList + */ + REGION_COPY(pScreen, pRegion, oldWinClip); + REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); + REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) + { + if (gravitate[g]) + REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, + gravitate[g]); + } + REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else + { + REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); + REGION_DESTROY(pScreen, oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = NULL; + + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); + + /* clip to not overwrite already copied areas */ + + if (destClip) { + REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); + REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); + REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y) + (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); + + /* remove any overwritten bits from the remaining useful bits */ + + REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->winGravity != g) + continue; + REGION_INTERSECT(pScreen, pRegion, + &pChild->borderClip, gravitate[g]); + TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (!destClip) + destClip = gravitate[g]; + else + { + REGION_UNION(pScreen, destClip, destClip, gravitate[g]); + REGION_DESTROY(pScreen, gravitate[g]); + } + } + + REGION_DESTROY(pScreen, oldRegion); + REGION_DESTROY(pScreen, pRegion); + if (destClip) + REGION_DESTROY(pScreen, destClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, + VTOther); + } + else if (bsExposed) + { + (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (pWin->realized) + WindowsRestructured (); +} + +WindowPtr +miGetLayerWindow(pWin) + WindowPtr pWin; +{ + return pWin->firstChild; +} + +#ifdef SHAPE +/****** + * + * miSetShape + * The border/window shape has changed. Recompute winSize/borderSize + * and send appropriate exposure events + */ + +void +miSetShape(pWin) + register WindowPtr pWin; +{ + Bool WasViewable = (Bool)(pWin->viewable); + register ScreenPtr pScreen = pWin->drawable.pScreen; + Bool anyMarked = FALSE; + RegionPtr pOldClip = NULL, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); +#ifdef NXAGENT_SERVER + + /* + * We got a few, rare, segfaults here after having + * started using the backing store. It may be a + * different bug but miChangeSaveUnder() calls mi- + * CheckSubSaveUnder() that, in turn, can change + * the backing store attribute of the window. This + * means that we may try to destroy the region + * even if it was not created at the beginning of + * this function as, at the time, the backing store + * was off. miCheckSubSaveUnder() appear to get a + * pointer to the parent, so maybe doesn't change + * the attribute of the window itself. This is to + * be better investigated. + */ + + if (WasViewable && pOldClip) + REGION_DESTROY(pScreen, pOldClip); +#else + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); +#endif + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + CheckCursorConfinement(pWin); +} +#endif + +/* Keeps the same inside(!) origin */ + +void +miChangeBorderWidth(pWin, width) + register WindowPtr pWin; + unsigned int width; +{ + WindowPtr pParent; + int oldwidth; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + Bool WasViewable = (Bool)(pWin->viewable); + Bool HadBorder; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + oldwidth = wBorderWidth (pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + pParent = pWin->parent; + if (WasViewable && width < oldwidth) + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + + pWin->borderWidth = width; + SetBorderSize (pWin); + + if (WasViewable) + { + if (width > oldwidth) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + /* + * save the old border visible region to correctly compute + * borderExposed. + */ + if (pWin->valdata && HadBorder) + { + RegionPtr borderVisible; + borderVisible = REGION_CREATE(pScreen, NULL, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, + VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +miMarkUnrealizedWindow(pChild, pWin, fromConfigure) + WindowPtr pChild; + WindowPtr pWin; + Bool fromConfigure; +{ + if ((pChild != pWin) || fromConfigure) + { + REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); + REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); + } +} + +void +miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) +{ + ScreenPtr pScreen; + WindowPtr pChild; + + pScreen = pWin->drawable.pScreen; + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->drawable.depth == depth) + REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); + + if (pChild->firstChild) + miSegregateChildren(pChild, pReg, depth); + } +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.NX.original new file mode 100644 index 000000000..ea2e7df28 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.NX.original @@ -0,0 +1,1205 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXmiwindow.c" + +#else + +/* $XFree86: xc/programs/Xserver/mi/miwindow.c,v 1.7 2001/12/14 20:00:28 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: miwindow.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#include "X.h" +#include "miscstruct.h" +#include "region.h" +#include "mi.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" + +void +miClearToBackground(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x,y; + int w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + + /* compute everything using ints to avoid overflow */ + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + extents = &pWin->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pWin->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); + if (generateExposures) + (*pScreen->WindowExposures)(pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +/* + * For SaveUnders using backing-store. The idea is that when a window is mapped + * with saveUnder set TRUE, any windows it obscures will have its backing + * store turned on setting the DIXsaveUnder bit, + * The backing-store code must be written to allow for this + */ + +/*- + *----------------------------------------------------------------------- + * miCheckSubSaveUnder -- + * Check all the inferiors of a window for coverage by saveUnder + * windows. Called from ChangeSaveUnder and CheckSaveUnder. + * This code is very inefficient. + * + * Results: + * TRUE if any windows need to have backing-store removed. + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +static Bool +miCheckSubSaveUnder( + register WindowPtr pParent, /* Parent to check */ + WindowPtr pFirst, /* first reconfigured window */ + RegionPtr pRegion) /* Initial area obscured by saveUnder */ +{ + register WindowPtr pChild; /* Current child */ + register ScreenPtr pScreen; /* Screen to use */ + RegionRec SubRegion; /* Area of children obscured */ + Bool res = FALSE; /* result */ + Bool subInited=FALSE;/* SubRegion initialized */ + + pScreen = pParent->drawable.pScreen; + if ( (pChild = pParent->firstChild) ) + { + /* + * build region above first changed window + */ + + for (; pChild != pFirst; pChild = pChild->nextSib) + if (pChild->viewable && pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + + /* + * check region below and including first changed window + */ + + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + { + /* + * don't save under nephew/niece windows; + * use a separate region + */ + + if (pChild->firstChild) + { + if (!subInited) + { + REGION_INIT(pScreen, &SubRegion, NullBox, 0); + subInited = TRUE; + } + REGION_COPY(pScreen, &SubRegion, pRegion); + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + &SubRegion); + } + else + { + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + pRegion); + } + + if (pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + } + } + + if (subInited) + REGION_UNINIT(pScreen, &SubRegion); + } + + /* + * Check the state of this window. DIX save unders are + * enabled for viewable windows with some client expressing + * exposure interest and which intersect the save under region + */ + + if (pParent->viewable && + ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && + REGION_NOTEMPTY(pScreen, &pParent->borderSize) && + RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, + &pParent->borderSize)) != rgnOUT) + { + if (!pParent->DIXsaveUnder) + { + pParent->DIXsaveUnder = TRUE; + (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); + } + } + else + { + if (pParent->DIXsaveUnder) + { + res = TRUE; + pParent->DIXsaveUnder = FALSE; + } + } + return res; +} + + +/*- + *----------------------------------------------------------------------- + * miChangeSaveUnder -- + * Change the save-under state of a tree of windows. Called when + * a window with saveUnder TRUE is mapped/unmapped/reconfigured. + * + * Results: + * TRUE if any windows need to have backing-store removed (which + * means that PostChangeSaveUnder needs to be called later to + * finish the job). + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +Bool +miChangeSaveUnder(pWin, first) + register WindowPtr pWin; + WindowPtr first; /* First window to check. + * Used when pWin was restacked */ +{ + RegionRec rgn; /* Area obscured by saveUnder windows */ + register ScreenPtr pScreen; + Bool res; + + if (!deltaSaveUndersViewable && !numSaveUndersViewable) + return FALSE; + numSaveUndersViewable += deltaSaveUndersViewable; + deltaSaveUndersViewable = 0; + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, &rgn, NullBox, 1); + res = miCheckSubSaveUnder (pWin->parent, + pWin->saveUnder ? first : pWin->nextSib, + &rgn); + REGION_UNINIT(pScreen, &rgn); + return res; +} + +/*- + *----------------------------------------------------------------------- + * miPostChangeSaveUnder -- + * Actually turn backing-store off for those windows that no longer + * need to have it on. + * + * Results: + * None. + * + * Side Effects: + * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those + * windows affected. + * + *----------------------------------------------------------------------- + */ +void +miPostChangeSaveUnder(pWin, pFirst) + WindowPtr pWin; + WindowPtr pFirst; +{ + register WindowPtr pParent, pChild; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + if (!(pParent = pWin->parent)) + return; + ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; + if (!pParent->DIXsaveUnder && + (pParent->backingStore == NotUseful) && pParent->backStorage) + (*ChangeWindowAttributes)(pParent, CWBackingStore); + if (!(pChild = pFirst)) + return; + while (1) + { + if (!pChild->DIXsaveUnder && + (pChild->backingStore == NotUseful) && pChild->backStorage) + (*ChangeWindowAttributes)(pChild, CWBackingStore); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib) + { + pChild = pChild->parent; + if (pChild == pParent) + return; + } + pChild = pChild->nextSib; + } +} + +void +miMarkWindow(pWin) + register WindowPtr pWin; +{ + register ValidatePtr val; + + if (pWin->valdata) + return; + val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); + val->before.oldAbsCorner.x = pWin->drawable.x; + val->before.oldAbsCorner.y = pWin->drawable.y; + val->before.borderVisible = NullRegion; + val->before.resized = FALSE; + pWin->valdata = val; +} + +Bool +miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) + WindowPtr pWin; + WindowPtr pFirst; + WindowPtr *ppLayerWin; +{ + register BoxPtr box; + register WindowPtr pChild, pLast; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + + /* 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 ( (pChild = pFirst) ) + { + box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); + pLast = pChild->parent->lastChild; + while (1) + { + if (pChild->viewable) + { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) + { + (* MarkWindow)(pChild); + anyMarked = TRUE; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + } + while (!pChild->nextSib && (pChild != pLast)) + pChild = pChild->parent; + if (pChild == pLast) + break; + pChild = pChild->nextSib; + } + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + return anyMarked; +} + +/***** + * miHandleValidateExposures(pWin) + * starting at pWin, draw background in any windows that have exposure + * regions, translate the regions, restore any backing store, + * and then send any regions still exposed to the client + *****/ +void +miHandleValidateExposures(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + register ValidatePtr val; + ScreenPtr pScreen; + WindowExposuresProcPtr WindowExposures; + + pScreen = pWin->drawable.pScreen; + + pChild = pWin; + WindowExposures = pChild->drawable.pScreen->WindowExposures; + while (1) + { + if ( (val = pChild->valdata) ) + { + if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) + (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, + &val->after.borderExposed, + PW_BORDER); + REGION_UNINIT(pScreen, &val->after.borderExposed); + (*WindowExposures)(pChild, &val->after.exposed, NullRegion); + REGION_UNINIT(pScreen, &val->after.exposed); + xfree(val); + pChild->valdata = (ValidatePtr)NULL; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +void +miMoveWindow(pWin, x, y, pNextSib, kind) + register WindowPtr pWin; + int x,y; + WindowPtr pNextSib; + VTKind kind; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + short bw; + RegionPtr oldRegion = NULL; + DDXPointRec oldpt; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr windowToValidate; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return ; + pScreen = pWin->drawable.pScreen; + bw = wBorderWidth (pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) + { + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->borderClip); + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + } + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + SetWinSize (pWin); + SetBorderSize (pWin); + + (*pScreen->PositionWindow)(pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) + { + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, windowToValidate, (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, pLayerWin, (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); + (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); + REGION_DESTROY(pScreen, oldRegion); + /* XXX need to retile border if ParentRelative origin */ + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + + +/* + * pValid is a region of the screen which has been + * successfully copied -- recomputed exposed regions for affected windows + */ + +static int +miRecomputeExposures ( + register WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + register ScreenPtr pScreen; + RegionPtr pValid = (RegionPtr)value; + + if (pWin->valdata) + { + pScreen = pWin->drawable.pScreen; + /* + * compute exposed regions of this window + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->clipList, pValid); + /* + * compute exposed regions of the border + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid); + return WT_WALKCHILDREN; + } + return WT_NOMATCH; +} + +void +miSlideAndSizeWindow(pWin, x, y, w, h, pSib) + register WindowPtr pWin; + int x,y; + unsigned int w, h; + WindowPtr pSib; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + unsigned short width = pWin->drawable.width, + height = pWin->drawable.height; + short oldx = pWin->drawable.x, + oldy = pWin->drawable.y; + int bw = wBorderWidth (pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion = NULL; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr pFirstChange; + register WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + register unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion = NULL; + RegionPtr destClip; /* portions of destination already written */ + RegionPtr oldWinClip = NULL; /* old clip list for window */ + RegionPtr borderVisible = NullRegion; /* visible area of the border */ + RegionPtr bsExposed = NullRegion; /* backing store exposures */ + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return ; + + pScreen = pWin->drawable.pScreen; + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) + { + anyMarked = FALSE; + /* + * save the visible region of the window + */ + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->winSize); + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = (RegionPtr) NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + g = pChild->winGravity; + if (g != UnmapGravity) + { + if (!gravitate[g]) + gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); + REGION_UNION(pScreen, gravitate[g], + gravitate[g], &pChild->borderClip); + } + else + { + UnmapWindow(pChild, TRUE); + anyMarked = TRUE; + } + } + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + + oldWinClip = NULL; + if (pWin->bitGravity != ForgetGravity) + { + oldWinClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldWinClip, &pWin->clipList); + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder (pWin)) + { + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) + { + if (shrunk || moved) + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, + &pWin->winSize); + else + REGION_COPY(pScreen, borderVisible, + &pWin->borderClip); + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize (pWin); + SetBorderSize (pWin); + + dw = (int)w - (int)width; + dh = (int)h - (int)height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow)(pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + pRegion = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->backStorage) + REGION_COPY(pScreen, pRegion, &pWin->clipList); + + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + + if (pWin->valdata) + { + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); + } + + GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pRegion = &pWin->clipList; /* a convenient empty region */ + if (pWin->bitGravity == ForgetGravity) + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, NullRegion, oldx, oldy); + else + { + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, nx - x, ny - y, pRegion, oldx, oldy); + } + } + + if (WasViewable) + { + /* avoid the border */ + if (HasBorder (pWin)) + { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) + { + REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip) + { + /* + * clip to new clipList + */ + REGION_COPY(pScreen, pRegion, oldWinClip); + REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); + REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) + { + if (gravitate[g]) + REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, + gravitate[g]); + } + REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else + { + REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); + REGION_DESTROY(pScreen, oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = NULL; + + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); + + /* clip to not overwrite already copied areas */ + + if (destClip) { + REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); + REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); + REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y) + (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); + + /* remove any overwritten bits from the remaining useful bits */ + + REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->winGravity != g) + continue; + REGION_INTERSECT(pScreen, pRegion, + &pChild->borderClip, gravitate[g]); + TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (!destClip) + destClip = gravitate[g]; + else + { + REGION_UNION(pScreen, destClip, destClip, gravitate[g]); + REGION_DESTROY(pScreen, gravitate[g]); + } + } + + REGION_DESTROY(pScreen, oldRegion); + REGION_DESTROY(pScreen, pRegion); + if (destClip) + REGION_DESTROY(pScreen, destClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, + VTOther); + } + else if (bsExposed) + { + (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (pWin->realized) + WindowsRestructured (); +} + +WindowPtr +miGetLayerWindow(pWin) + WindowPtr pWin; +{ + return pWin->firstChild; +} + +#ifdef SHAPE +/****** + * + * miSetShape + * The border/window shape has changed. Recompute winSize/borderSize + * and send appropriate exposure events + */ + +void +miSetShape(pWin) + register WindowPtr pWin; +{ + Bool WasViewable = (Bool)(pWin->viewable); + register ScreenPtr pScreen = pWin->drawable.pScreen; + Bool anyMarked = FALSE; + RegionPtr pOldClip = NULL, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); +#ifdef NXAGENT_SERVER + + /* + * We got a few, rare, segfaults here after having + * started using the backing store. It may be a + * different bug but miChangeSaveUnder() calls mi- + * CheckSubSaveUnder() that, in turn, can change + * the backing store attribute of the window. This + * means that we may try to destroy the region + * even if it was not created at the beginning of + * this function as, at the time, the backing store + * was off. miCheckSubSaveUnder() appear to get a + * pointer to the parent, so maybe doesn't change + * the attribute of the window itself. This is to + * be better investigated. + */ + + if (WasViewable && pOldClip) + REGION_DESTROY(pScreen, pOldClip); +#else + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); +#endif + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + CheckCursorConfinement(pWin); +} +#endif + +/* Keeps the same inside(!) origin */ + +void +miChangeBorderWidth(pWin, width) + register WindowPtr pWin; + unsigned int width; +{ + WindowPtr pParent; + int oldwidth; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + Bool WasViewable = (Bool)(pWin->viewable); + Bool HadBorder; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + oldwidth = wBorderWidth (pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + pParent = pWin->parent; + if (WasViewable && width < oldwidth) + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + + pWin->borderWidth = width; + SetBorderSize (pWin); + + if (WasViewable) + { + if (width > oldwidth) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + /* + * save the old border visible region to correctly compute + * borderExposed. + */ + if (pWin->valdata && HadBorder) + { + RegionPtr borderVisible; + borderVisible = REGION_CREATE(pScreen, NULL, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, + VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +miMarkUnrealizedWindow(pChild, pWin, fromConfigure) + WindowPtr pChild; + WindowPtr pWin; + Bool fromConfigure; +{ + if ((pChild != pWin) || fromConfigure) + { + REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); + REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); + } +} + +void +miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) +{ + ScreenPtr pScreen; + WindowPtr pChild; + + pScreen = pWin->drawable.pScreen; + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->drawable.depth == depth) + REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); + + if (pChild->firstChild) + miSegregateChildren(pChild, pReg, depth); + } +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.XF86.original new file mode 100644 index 000000000..fbced41c6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.XF86.original @@ -0,0 +1,1176 @@ +/* $XFree86: xc/programs/Xserver/mi/miwindow.c,v 1.7 2001/12/14 20:00:28 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: miwindow.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#include "X.h" +#include "miscstruct.h" +#include "region.h" +#include "mi.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" + +void +miClearToBackground(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x,y; + int w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + + /* compute everything using ints to avoid overflow */ + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + extents = &pWin->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pWin->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); + if (generateExposures) + (*pScreen->WindowExposures)(pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +/* + * For SaveUnders using backing-store. The idea is that when a window is mapped + * with saveUnder set TRUE, any windows it obscures will have its backing + * store turned on setting the DIXsaveUnder bit, + * The backing-store code must be written to allow for this + */ + +/*- + *----------------------------------------------------------------------- + * miCheckSubSaveUnder -- + * Check all the inferiors of a window for coverage by saveUnder + * windows. Called from ChangeSaveUnder and CheckSaveUnder. + * This code is very inefficient. + * + * Results: + * TRUE if any windows need to have backing-store removed. + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +static Bool +miCheckSubSaveUnder( + register WindowPtr pParent, /* Parent to check */ + WindowPtr pFirst, /* first reconfigured window */ + RegionPtr pRegion) /* Initial area obscured by saveUnder */ +{ + register WindowPtr pChild; /* Current child */ + register ScreenPtr pScreen; /* Screen to use */ + RegionRec SubRegion; /* Area of children obscured */ + Bool res = FALSE; /* result */ + Bool subInited=FALSE;/* SubRegion initialized */ + + pScreen = pParent->drawable.pScreen; + if ( (pChild = pParent->firstChild) ) + { + /* + * build region above first changed window + */ + + for (; pChild != pFirst; pChild = pChild->nextSib) + if (pChild->viewable && pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + + /* + * check region below and including first changed window + */ + + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + { + /* + * don't save under nephew/niece windows; + * use a separate region + */ + + if (pChild->firstChild) + { + if (!subInited) + { + REGION_INIT(pScreen, &SubRegion, NullBox, 0); + subInited = TRUE; + } + REGION_COPY(pScreen, &SubRegion, pRegion); + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + &SubRegion); + } + else + { + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + pRegion); + } + + if (pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + } + } + + if (subInited) + REGION_UNINIT(pScreen, &SubRegion); + } + + /* + * Check the state of this window. DIX save unders are + * enabled for viewable windows with some client expressing + * exposure interest and which intersect the save under region + */ + + if (pParent->viewable && + ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && + REGION_NOTEMPTY(pScreen, &pParent->borderSize) && + RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, + &pParent->borderSize)) != rgnOUT) + { + if (!pParent->DIXsaveUnder) + { + pParent->DIXsaveUnder = TRUE; + (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); + } + } + else + { + if (pParent->DIXsaveUnder) + { + res = TRUE; + pParent->DIXsaveUnder = FALSE; + } + } + return res; +} + + +/*- + *----------------------------------------------------------------------- + * miChangeSaveUnder -- + * Change the save-under state of a tree of windows. Called when + * a window with saveUnder TRUE is mapped/unmapped/reconfigured. + * + * Results: + * TRUE if any windows need to have backing-store removed (which + * means that PostChangeSaveUnder needs to be called later to + * finish the job). + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +Bool +miChangeSaveUnder(pWin, first) + register WindowPtr pWin; + WindowPtr first; /* First window to check. + * Used when pWin was restacked */ +{ + RegionRec rgn; /* Area obscured by saveUnder windows */ + register ScreenPtr pScreen; + Bool res; + + if (!deltaSaveUndersViewable && !numSaveUndersViewable) + return FALSE; + numSaveUndersViewable += deltaSaveUndersViewable; + deltaSaveUndersViewable = 0; + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, &rgn, NullBox, 1); + res = miCheckSubSaveUnder (pWin->parent, + pWin->saveUnder ? first : pWin->nextSib, + &rgn); + REGION_UNINIT(pScreen, &rgn); + return res; +} + +/*- + *----------------------------------------------------------------------- + * miPostChangeSaveUnder -- + * Actually turn backing-store off for those windows that no longer + * need to have it on. + * + * Results: + * None. + * + * Side Effects: + * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those + * windows affected. + * + *----------------------------------------------------------------------- + */ +void +miPostChangeSaveUnder(pWin, pFirst) + WindowPtr pWin; + WindowPtr pFirst; +{ + register WindowPtr pParent, pChild; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + if (!(pParent = pWin->parent)) + return; + ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; + if (!pParent->DIXsaveUnder && + (pParent->backingStore == NotUseful) && pParent->backStorage) + (*ChangeWindowAttributes)(pParent, CWBackingStore); + if (!(pChild = pFirst)) + return; + while (1) + { + if (!pChild->DIXsaveUnder && + (pChild->backingStore == NotUseful) && pChild->backStorage) + (*ChangeWindowAttributes)(pChild, CWBackingStore); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib) + { + pChild = pChild->parent; + if (pChild == pParent) + return; + } + pChild = pChild->nextSib; + } +} + +void +miMarkWindow(pWin) + register WindowPtr pWin; +{ + register ValidatePtr val; + + if (pWin->valdata) + return; + val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); + val->before.oldAbsCorner.x = pWin->drawable.x; + val->before.oldAbsCorner.y = pWin->drawable.y; + val->before.borderVisible = NullRegion; + val->before.resized = FALSE; + pWin->valdata = val; +} + +Bool +miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) + WindowPtr pWin; + WindowPtr pFirst; + WindowPtr *ppLayerWin; +{ + register BoxPtr box; + register WindowPtr pChild, pLast; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + + /* 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 ( (pChild = pFirst) ) + { + box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); + pLast = pChild->parent->lastChild; + while (1) + { + if (pChild->viewable) + { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) + { + (* MarkWindow)(pChild); + anyMarked = TRUE; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + } + while (!pChild->nextSib && (pChild != pLast)) + pChild = pChild->parent; + if (pChild == pLast) + break; + pChild = pChild->nextSib; + } + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + return anyMarked; +} + +/***** + * miHandleValidateExposures(pWin) + * starting at pWin, draw background in any windows that have exposure + * regions, translate the regions, restore any backing store, + * and then send any regions still exposed to the client + *****/ +void +miHandleValidateExposures(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + register ValidatePtr val; + ScreenPtr pScreen; + WindowExposuresProcPtr WindowExposures; + + pScreen = pWin->drawable.pScreen; + + pChild = pWin; + WindowExposures = pChild->drawable.pScreen->WindowExposures; + while (1) + { + if ( (val = pChild->valdata) ) + { + if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) + (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, + &val->after.borderExposed, + PW_BORDER); + REGION_UNINIT(pScreen, &val->after.borderExposed); + (*WindowExposures)(pChild, &val->after.exposed, NullRegion); + REGION_UNINIT(pScreen, &val->after.exposed); + xfree(val); + pChild->valdata = (ValidatePtr)NULL; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +void +miMoveWindow(pWin, x, y, pNextSib, kind) + register WindowPtr pWin; + int x,y; + WindowPtr pNextSib; + VTKind kind; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + short bw; + RegionPtr oldRegion = NULL; + DDXPointRec oldpt; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr windowToValidate; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return ; + pScreen = pWin->drawable.pScreen; + bw = wBorderWidth (pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) + { + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->borderClip); + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + } + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + SetWinSize (pWin); + SetBorderSize (pWin); + + (*pScreen->PositionWindow)(pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) + { + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, windowToValidate, (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, pLayerWin, (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); + (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); + REGION_DESTROY(pScreen, oldRegion); + /* XXX need to retile border if ParentRelative origin */ + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + + +/* + * pValid is a region of the screen which has been + * successfully copied -- recomputed exposed regions for affected windows + */ + +static int +miRecomputeExposures ( + register WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + register ScreenPtr pScreen; + RegionPtr pValid = (RegionPtr)value; + + if (pWin->valdata) + { + pScreen = pWin->drawable.pScreen; + /* + * compute exposed regions of this window + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->clipList, pValid); + /* + * compute exposed regions of the border + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid); + return WT_WALKCHILDREN; + } + return WT_NOMATCH; +} + +void +miSlideAndSizeWindow(pWin, x, y, w, h, pSib) + register WindowPtr pWin; + int x,y; + unsigned int w, h; + WindowPtr pSib; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + unsigned short width = pWin->drawable.width, + height = pWin->drawable.height; + short oldx = pWin->drawable.x, + oldy = pWin->drawable.y; + int bw = wBorderWidth (pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion = NULL; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr pFirstChange; + register WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + register unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion = NULL; + RegionPtr destClip; /* portions of destination already written */ + RegionPtr oldWinClip = NULL; /* old clip list for window */ + RegionPtr borderVisible = NullRegion; /* visible area of the border */ + RegionPtr bsExposed = NullRegion; /* backing store exposures */ + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return ; + + pScreen = pWin->drawable.pScreen; + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) + { + anyMarked = FALSE; + /* + * save the visible region of the window + */ + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->winSize); + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = (RegionPtr) NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + g = pChild->winGravity; + if (g != UnmapGravity) + { + if (!gravitate[g]) + gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); + REGION_UNION(pScreen, gravitate[g], + gravitate[g], &pChild->borderClip); + } + else + { + UnmapWindow(pChild, TRUE); + anyMarked = TRUE; + } + } + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + + oldWinClip = NULL; + if (pWin->bitGravity != ForgetGravity) + { + oldWinClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldWinClip, &pWin->clipList); + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder (pWin)) + { + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) + { + if (shrunk || moved) + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, + &pWin->winSize); + else + REGION_COPY(pScreen, borderVisible, + &pWin->borderClip); + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize (pWin); + SetBorderSize (pWin); + + dw = (int)w - (int)width; + dh = (int)h - (int)height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow)(pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + pRegion = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->backStorage) + REGION_COPY(pScreen, pRegion, &pWin->clipList); + + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + + if (pWin->valdata) + { + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); + } + + GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pRegion = &pWin->clipList; /* a convenient empty region */ + if (pWin->bitGravity == ForgetGravity) + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, NullRegion, oldx, oldy); + else + { + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, nx - x, ny - y, pRegion, oldx, oldy); + } + } + + if (WasViewable) + { + /* avoid the border */ + if (HasBorder (pWin)) + { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) + { + REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip) + { + /* + * clip to new clipList + */ + REGION_COPY(pScreen, pRegion, oldWinClip); + REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); + REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) + { + if (gravitate[g]) + REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, + gravitate[g]); + } + REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else + { + REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); + REGION_DESTROY(pScreen, oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = NULL; + + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); + + /* clip to not overwrite already copied areas */ + + if (destClip) { + REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); + REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); + REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y) + (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); + + /* remove any overwritten bits from the remaining useful bits */ + + REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->winGravity != g) + continue; + REGION_INTERSECT(pScreen, pRegion, + &pChild->borderClip, gravitate[g]); + TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (!destClip) + destClip = gravitate[g]; + else + { + REGION_UNION(pScreen, destClip, destClip, gravitate[g]); + REGION_DESTROY(pScreen, gravitate[g]); + } + } + + REGION_DESTROY(pScreen, oldRegion); + REGION_DESTROY(pScreen, pRegion); + if (destClip) + REGION_DESTROY(pScreen, destClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, + VTOther); + } + else if (bsExposed) + { + (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (pWin->realized) + WindowsRestructured (); +} + +WindowPtr +miGetLayerWindow(pWin) + WindowPtr pWin; +{ + return pWin->firstChild; +} + +#ifdef SHAPE +/****** + * + * miSetShape + * The border/window shape has changed. Recompute winSize/borderSize + * and send appropriate exposure events + */ + +void +miSetShape(pWin) + register WindowPtr pWin; +{ + Bool WasViewable = (Bool)(pWin->viewable); + register ScreenPtr pScreen = pWin->drawable.pScreen; + Bool anyMarked = FALSE; + RegionPtr pOldClip = NULL, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + CheckCursorConfinement(pWin); +} +#endif + +/* Keeps the same inside(!) origin */ + +void +miChangeBorderWidth(pWin, width) + register WindowPtr pWin; + unsigned int width; +{ + WindowPtr pParent; + int oldwidth; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + Bool WasViewable = (Bool)(pWin->viewable); + Bool HadBorder; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + oldwidth = wBorderWidth (pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + pParent = pWin->parent; + if (WasViewable && width < oldwidth) + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + + pWin->borderWidth = width; + SetBorderSize (pWin); + + if (WasViewable) + { + if (width > oldwidth) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + /* + * save the old border visible region to correctly compute + * borderExposed. + */ + if (pWin->valdata && HadBorder) + { + RegionPtr borderVisible; + borderVisible = REGION_CREATE(pScreen, NULL, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, + VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +miMarkUnrealizedWindow(pChild, pWin, fromConfigure) + WindowPtr pChild; + WindowPtr pWin; + Bool fromConfigure; +{ + if ((pChild != pWin) || fromConfigure) + { + REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); + REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); + } +} + +void +miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) +{ + ScreenPtr pScreen; + WindowPtr pChild; + + pScreen = pWin->drawable.pScreen; + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->drawable.depth == depth) + REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); + + if (pChild->firstChild) + miSegregateChildren(pChild, pReg, depth); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c new file mode 100644 index 000000000..64ba970c9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c @@ -0,0 +1,1512 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXpicture.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/picture.c,v 1.30 2003/01/26 16:40:43 eich Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "NXpicturestr.h" + +#include "Screen.h" +#include "Pixmaps.h" +#include "Drawable.h" + +void *nxagentMatchingFormats(PictFormatPtr pForm); + +int PictureScreenPrivateIndex = -1; +int PictureWindowPrivateIndex; +int PictureGeneration; +RESTYPE PictureType; +RESTYPE PictFormatType; +RESTYPE GlyphSetType; +int PictureCmapPolicy = PictureCmapPolicyDefault; + +Bool +PictureDestroyWindow (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + + while ((pPicture = GetPictureWindow(pWindow))) + { + SetPictureWindow(pWindow, pPicture->pNext); + if (pPicture->id) + FreeResource (pPicture->id, PictureType); + FreePicture ((pointer) pPicture, pPicture->id); + } + pScreen->DestroyWindow = ps->DestroyWindow; + ret = (*pScreen->DestroyWindow) (pWindow); + ps->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = PictureDestroyWindow; + return ret; +} + +Bool +PictureCloseScreen (int index, ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + int n; + + pScreen->CloseScreen = ps->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + PictureResetFilters (pScreen); + for (n = 0; n < ps->nformats; n++) + if (ps->formats[n].type == PictTypeIndexed) + (*ps->CloseIndexed) (pScreen, &ps->formats[n]); + SetPictureScreen(pScreen, 0); + xfree (ps->formats); + xfree (ps); + return ret; +} + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + pScreen->StoreColors = ps->StoreColors; + (*pScreen->StoreColors) (pColormap, ndef, pdef); + ps->StoreColors = pScreen->StoreColors; + pScreen->StoreColors = PictureStoreColors; + + if (pColormap->class == PseudoColor || pColormap->class == GrayScale) + { + PictFormatPtr format = ps->formats; + int nformats = ps->nformats; + + while (nformats--) + { + if (format->type == PictTypeIndexed && + format->index.pColormap == pColormap) + { + (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); + break; + } + format++; + } + } +} + +static int +visualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + int d, v; + DepthPtr pDepth; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + return 0; +} + +typedef struct _formatInit { + CARD32 format; + CARD8 depth; +} FormatInitRec, *FormatInitPtr; + +static int +addFormat (FormatInitRec formats[256], + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + formats[nformat].format = format; + formats[nformat].depth = depth; + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) +{ +#ifdef NXAGENT_SERVER + int nformats, f, n; +#else + int nformats, f; +#endif + PictFormatPtr pFormats; + FormatInitRec formats[1024]; + CARD32 format; + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int type; + int r, g, b; + int d; + DepthPtr pDepth; + + nformats = 0; + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + formats[nformats].format = PICT_x8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + bpp = BitsPerPixel (depth); + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + type = PICT_TYPE_OTHER; + /* + * Current rendering code supports only two direct formats, + * fields must be packed together at the bottom of the pixel + * and must be either RGB or BGR + */ + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + type = PICT_TYPE_ARGB; + } + else if (pVisual->offsetRed == 0 && + pVisual->offsetGreen == r && + pVisual->offsetBlue == r + g) + { + type = PICT_TYPE_ABGR; + } + if (type != PICT_TYPE_OTHER) + { + format = PICT_FORMAT(bpp, type, 0, r, g, b); + nformats = addFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); + nformats = addFormat (formats, nformats, format, depth); + break; + case StaticGray: + case GrayScale: + format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); + nformats = addFormat (formats, nformats, format, depth); + break; + } + } + /* + * Walk supported depths and add useful Direct formats + */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + switch (bpp) { + case 16: + /* depth 12 formats */ + if (pDepth->depth >= 12) + { + nformats = addFormat (formats, nformats, + PICT_x4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x4b4g4r4, pDepth->depth); + } + /* depth 15 formats */ + if (pDepth->depth >= 15) + { + nformats = addFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x1b5g5r5, pDepth->depth); + } + /* depth 16 formats */ + if (pDepth->depth >= 16) + { + nformats = addFormat (formats, nformats, + PICT_a1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a1b5g5r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b5g6r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4b4g4r4, pDepth->depth); + } + break; + case 24: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b8g8r8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x8b8g8r8, pDepth->depth); + } + break; + } + } + + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); +#ifdef NXAGENT_SERVER + for (f = 0, n = 0; n < nformats; n++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[n].depth; + format = formats[n].format; + pFormats[f].format = format; +#else + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; +#endif + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_ARGB: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = (PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_B(format); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = 0; + break; + + case PICT_TYPE_ABGR: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = (PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_R(format); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = 0; + break; + + case PICT_TYPE_A: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + + /* remaining fields already set to zero */ + break; + + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + pFormats[f].type = PictTypeIndexed; + pFormats[f].index.pVisual = &pScreen->visuals[PICT_FORMAT_VIS(format)]; + break; + } + +#ifdef NXAGENT_SERVER + if (nxagentMatchingFormats(&pFormats[f]) != NULL) + { + f++; + } + else + { + memset(&pFormats[f], '\0', sizeof(PictFormatRec)); + } + } + *nformatp = f; +#else + } + *nformatp = nformats; +#endif + return pFormats; +} + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return FALSE; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->type == PictTypeIndexed && !format->index.pColormap) + { + if (format->index.pVisual->vid == pScreen->rootVisual) + format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + else + { + if (CreateColormap (FakeClientID (0), pScreen, + format->index.pVisual, + &format->index.pColormap, AllocNone, + 0) != Success) + { + return FALSE; + } + } + if (!(*ps->InitIndexed) (pScreen, format)) + return FALSE; + } + format++; + } + return TRUE; +} + +Bool +PictureFinishInit (void) +{ + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + { + if (!PictureInitIndexedFormats (screenInfo.screens[s])) + return FALSE; + (void) AnimCurInit (screenInfo.screens[s]); + } + + return TRUE; +} + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return FALSE; + ps->subpixel = subpixel; + return TRUE; + +} + +int +PictureGetSubpixelOrder (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return SubPixelUnknown; + return ps->subpixel; +} + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + int type; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + switch (pVisual->class) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + type = PictTypeIndexed; + break; + case TrueColor: + type = PictTypeDirect; + break; + case DirectColor: + default: + return 0; + } + while (nformat--) + { + if (format->depth == depth && format->type == type) + { + if (type == PictTypeIndexed) + { + if (format->index.pVisual == pVisual) + return format; + } + else + { + if (format->direct.redMask << format->direct.red == + pVisual->redMask && + format->direct.greenMask << format->direct.green == + pVisual->greenMask && + format->direct.blueMask << format->direct.blue == + pVisual->blueMask) + { + return format; + } + } + } + format++; + } + return 0; +} + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->depth == depth && format->format == (f & 0xffffff)) + return format; + format++; + } + return 0; +} + +int +PictureParseCmapPolicy (const char *name) +{ + if ( strcmp (name, "default" ) == 0) + return PictureCmapPolicyDefault; + else if ( strcmp (name, "mono" ) == 0) + return PictureCmapPolicyMono; + else if ( strcmp (name, "gray" ) == 0) + return PictureCmapPolicyGray; + else if ( strcmp (name, "color" ) == 0) + return PictureCmapPolicyColor; + else if ( strcmp (name, "all" ) == 0) + return PictureCmapPolicyAll; + else + return PictureCmapPolicyInvalid; +} + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + int n; + CARD32 type, a, r, g, b; + + if (PictureGeneration != serverGeneration) + { + PictureType = CreateNewResourceType (FreePicture); + if (!PictureType) + return FALSE; + PictFormatType = CreateNewResourceType (FreePictFormat); + if (!PictFormatType) + return FALSE; + GlyphSetType = CreateNewResourceType (FreeGlyphSet); + if (!GlyphSetType) + return FALSE; + PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (PictureScreenPrivateIndex < 0) + return FALSE; + PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); + PictureGeneration = serverGeneration; +#ifdef XResExtension + RegisterResourceName (PictureType, "PICTURE"); + RegisterResourceName (PictFormatType, "PICTFORMAT"); + RegisterResourceName (GlyphSetType, "GLYPHSET"); +#endif + } + if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) + return FALSE; + + if (!formats) + { + formats = PictureCreateDefaultFormats (pScreen, &nformats); + if (!formats) + return FALSE; + } + for (n = 0; n < nformats; n++) + { + if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) + { + xfree (formats); + return FALSE; + } + if (formats[n].type == PictTypeIndexed) + { + if ((formats[n].index.pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); + if (!ps) + { + xfree (formats); + return FALSE; + } + SetPictureScreen(pScreen, ps); + if (!GlyphInit (pScreen)) + { + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + ps->totalPictureSize = sizeof (PictureRec); + ps->PicturePrivateSizes = 0; + ps->PicturePrivateLen = 0; + + ps->formats = formats; + ps->fallback = formats; + ps->nformats = nformats; + + ps->filters = 0; + ps->nfilters = 0; + ps->filterAliases = 0; + ps->nfilterAliases = 0; + + ps->subpixel = SubPixelUnknown; + + ps->CloseScreen = pScreen->CloseScreen; + ps->DestroyWindow = pScreen->DestroyWindow; + ps->StoreColors = pScreen->StoreColors; + pScreen->DestroyWindow = PictureDestroyWindow; + pScreen->CloseScreen = PictureCloseScreen; + pScreen->StoreColors = PictureStoreColors; + + if (!PictureSetDefaultFilters (pScreen)) + { + PictureResetFilters (pScreen); + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + return TRUE; +} + +void +SetPictureToDefaults (PicturePtr pPicture) +{ + pPicture->refcnt = 1; + pPicture->repeat = 0; + pPicture->graphicsExposures = FALSE; + pPicture->subWindowMode = ClipByChildren; + pPicture->polyEdge = PolyEdgeSharp; + pPicture->polyMode = PolyModePrecise; + pPicture->freeCompClip = FALSE; + pPicture->clientClipType = CT_NONE; + pPicture->componentAlpha = FALSE; + + pPicture->alphaMap = 0; + pPicture->alphaOrigin.x = 0; + pPicture->alphaOrigin.y = 0; + + pPicture->clipOrigin.x = 0; + pPicture->clipOrigin.y = 0; + pPicture->clientClip = 0; + + pPicture->transform = 0; + + pPicture->dither = None; + pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); + pPicture->filter_params = 0; + pPicture->filter_nparams = 0; + + pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; + pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; +} + +PicturePtr +AllocatePicture (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture; + char *ptr; + DevUnion *ppriv; + unsigned int *sizes; + unsigned int size; + int i; + + pPicture = (PicturePtr) xalloc (ps->totalPictureSize); + if (!pPicture) + return 0; + ppriv = (DevUnion *)(pPicture + 1); + pPicture->devPrivates = ppriv; + sizes = ps->PicturePrivateSizes; + ptr = (char *)(ppriv + ps->PicturePrivateLen); + for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return pPicture; +} + +/* + * Let picture always point to the virtual pixmap. + * For sure this is not the best way to deal with + * the virtual frame-buffer. + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask vmask, + XID *vlist, + ClientPtr client, + int *error) +{ + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); + + pPicture = AllocatePicture (pDrawable->pScreen); + if (!pPicture) + { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pDrawable = pDrawable; + pPicture->pFormat = pFormat; + pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); + if (pDrawable->type == DRAWABLE_PIXMAP) + { + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + pPicture->pDrawable = nxagentVirtualDrawable(pDrawable); + + #endif + + ++((PixmapPtr)pDrawable)->refcnt; + pPicture->pNext = 0; + } + else + { + pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); + SetPictureWindow(((WindowPtr) pDrawable), pPicture); + } + + SetPictureToDefaults (pPicture); + + if (vmask) + *error = ChangePicture (pPicture, vmask, vlist, 0, client); + else + *error = Success; + if (*error == Success) + *error = (*ps->CreatePicture) (pPicture); + if (*error != Success) + { + FreePicture (pPicture, (XID) 0); + pPicture = 0; + } + return pPicture; +} + +#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) + +#define NEXT_PTR(_type) ((_type) ulist++->ptr) + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BITS32 index2; + int error = 0; + BITS32 maskQ; + + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + maskQ = vmask; + while (vmask && !error) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + pPicture->stateChanges |= index2; + switch (index2) + { + case CPRepeat: + { + unsigned int newr; + newr = NEXT_VAL(unsigned int); + if (newr <= xTrue) + pPicture->repeat = newr; + else + { + client->errorValue = newr; + error = BadValue; + } + } + break; + case CPAlphaMap: + { + PicturePtr pAlpha; + + if (vlist) + { + Picture pid = NEXT_VAL(Picture); + + if (pid == None) + pAlpha = 0; + else + { + pAlpha = (PicturePtr) SecurityLookupIDByType(client, + pid, + PictureType, + SecurityWriteAccess|SecurityReadAccess); + if (!pAlpha) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + if (pAlpha->pDrawable->type != DRAWABLE_PIXMAP) + { + client->errorValue = pid; + error = BadMatch; + break; + } + } + } + else + pAlpha = NEXT_PTR(PicturePtr); + if (!error) + { + if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) + pAlpha->refcnt++; + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + pPicture->alphaMap = pAlpha; + } + } + break; + case CPAlphaXOrigin: + pPicture->alphaOrigin.x = NEXT_VAL(INT16); + break; + case CPAlphaYOrigin: + pPicture->alphaOrigin.y = NEXT_VAL(INT16); + break; + case CPClipXOrigin: + pPicture->clipOrigin.x = NEXT_VAL(INT16); + break; + case CPClipYOrigin: + pPicture->clipOrigin.y = NEXT_VAL(INT16); + break; + case CPClipMask: + { + Pixmap pid; + PixmapPtr pPixmap; + int clipType; + + if (vlist) + { + pid = NEXT_VAL(Pixmap); + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + { + clipType = CT_PIXMAP; + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + } + } + else + { + pPixmap = NEXT_PTR(PixmapPtr); + if (pPixmap) + clipType = CT_PIXMAP; + else + clipType = CT_NONE; + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + break; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + error = (*ps->ChangePictureClip)(pPicture, clipType, + (pointer)pPixmap, 0); + break; + } + case CPGraphicsExposure: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe <= xTrue) + pPicture->graphicsExposures = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPSubwindowMode: + { + unsigned int news; + news = NEXT_VAL(unsigned int); + if (news == ClipByChildren || news == IncludeInferiors) + pPicture->subWindowMode = news; + else + { + client->errorValue = news; + error = BadValue; + } + } + break; + case CPPolyEdge: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) + pPicture->polyEdge = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPPolyMode: + { + unsigned int newm; + newm = NEXT_VAL(unsigned int); + if (newm == PolyModePrecise || newm == PolyModeImprecise) + pPicture->polyMode = newm; + else + { + client->errorValue = newm; + error = BadValue; + } + } + break; + case CPDither: + pPicture->dither = NEXT_VAL(Atom); + break; + case CPComponentAlpha: + { + unsigned int newca; + + newca = NEXT_VAL (unsigned int); + if (newca <= xTrue) + pPicture->componentAlpha = newca; + else + { + client->errorValue = newca; + error = BadValue; + } + } + break; + default: + client->errorValue = maskQ; + error = BadValue; + break; + } + } + (*ps->ChangePicture) (pPicture, maskQ); + return error; +} + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + + clientClip = RECTS_TO_REGION(pScreen, + nRect, rects, CT_UNSORTED); + if (!clientClip) + return BadAlloc; + result =(*ps->ChangePictureClip) (pPicture, CT_REGION, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + static const PictTransform identity = { { + { xFixed1, 0x00000, 0x00000 }, + { 0x00000, xFixed1, 0x00000 }, + { 0x00000, 0x00000, xFixed1 }, + } }; + + if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0) + transform = 0; + + if (transform) + { + if (!pPicture->transform) + { + pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); + if (!pPicture->transform) + return BadAlloc; + } + *pPicture->transform = *transform; + } + else + { + if (pPicture->transform) + { + xfree (pPicture->transform); + pPicture->transform = 0; + } + } + return Success; +} + +static void +ValidateOnePicture (PicturePtr pPicture) +{ + if (pPicture->serialNumber != pPicture->pDrawable->serialNumber) + { + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); + pPicture->stateChanges = 0; + pPicture->serialNumber = pPicture->pDrawable->serialNumber; + } +} + +void +ValidatePicture(PicturePtr pPicture) +{ + ValidateOnePicture (pPicture); + if (pPicture->alphaMap) + ValidateOnePicture (pPicture->alphaMap); +} + +int +FreePicture (pointer value, + XID pid) +{ + PicturePtr pPicture = (PicturePtr) value; + + if (--pPicture->refcnt == 0) + { + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + (*ps->DestroyPicture) (pPicture); + (*ps->DestroyPictureClip) (pPicture); + if (pPicture->transform) + xfree (pPicture->transform); + if (pPicture->pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PicturePtr *pPrev; + + for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); + *pPrev; + pPrev = &(*pPrev)->pNext) + { + if (*pPrev == pPicture) + { + *pPrev = pPicture->pNext; + break; + } + } + } + else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) + { + (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); + } + xfree (pPicture); + } + return Success; +} + +int +FreePictFormat (pointer pPictFormat, + XID pid) +{ + return Success; +} + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); +} + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + + #ifdef TEST + fprintf(stderr, "CompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); +} + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pDst); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); +} + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); +} + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); +} + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +typedef xFixed_32_32 xFixed_48_16; + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + for (j = 0; j < 2; j++) + { + partial = (xFixed_48_16) result.vector[j] << 16; + v = partial / result.vector[2]; + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + vector->vector[j] = (xFixed) v; + } + vector->vector[2] = xFixed1; + return TRUE; +} + +#ifndef True +# define True 1 +#endif + +#ifndef False +# define False 0 +#endif + +void nxagentReconnectPictFormat(void*, XID, void*); + +Bool nxagentReconnectAllPictFormat(void *p) +{ + PictFormatPtr formats_old, formats; + int nformats, nformats_old; + Bool success = True; + Bool matched; + int i, n; + CARD32 type, a, r, g, b; + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectAllPictFormat\n"); + #endif + + formats_old = GetPictureScreen(nxagentDefaultScreen) -> formats; + nformats_old = GetPictureScreen(nxagentDefaultScreen) -> nformats; + + /* + * TODO: We could copy PictureCreateDefaultFormats, + * in order not to waste ID with FakeClientID(). + */ + formats = PictureCreateDefaultFormats (nxagentDefaultScreen, &nformats); + + if (!formats) + return FALSE; + + for (n = 0; n < nformats; n++) + { + if (formats[n].type == PictTypeIndexed) + { + if ((formats[n].index.pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + + for (n = 0; n < nformats_old; n++) + { + for (i = 0, matched = False; (!matched) && (i < nformats); i++) + { + if (formats_old[n].format == formats[i].format && + formats_old[n].type == formats[i].type && + formats_old[n].direct.red == formats[i].direct.red && + formats_old[n].direct.green == formats[i].direct.green && + formats_old[n].direct.blue == formats[i].direct.blue && + formats_old[n].direct.redMask == formats[i].direct.redMask && + formats_old[n].direct.greenMask == formats[i].direct.greenMask && + formats_old[n].direct.blueMask == formats[i].direct.blueMask && + formats_old[n].direct.alpha == formats[i].direct.alpha && + formats_old[n].direct.alphaMask == formats[i].direct.alphaMask) + { + /* + * Regard depth 16 and 15 as were the same, if all other values match. + */ + + if ((formats_old[n].depth == formats[i].depth) || + ((formats_old[n].depth == 15 || formats_old[n].depth == 16) && + (formats[i].depth == 15 || formats[i].depth == 16))) + { + matched = True; + } + } + } + if (!matched) + return False; + } + xfree(formats); + + /* TODO: Perhaps do i have to do PictureFinishInit ?. */ + /* TODO: We have to check for new Render protocol version. */ + + for (i = 0; (i < MAXCLIENTS) && (success); i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], PictFormatType, nxagentReconnectPictFormat, &success); + } + } + + return success; +} + +/* + * It seem we don't have nothing + * to do for reconnect PictureFormat. + */ + +void nxagentReconnectPictFormat(void *p0, XID x1, void *p2) +{ + PictFormatPtr pFormat; + Bool *pBool; + + pFormat = (PictFormatPtr)p0; + pBool = (Bool*)p2; + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectPictFormat.\n"); + #endif +} + + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.NX.original new file mode 100644 index 000000000..64ba970c9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.NX.original @@ -0,0 +1,1512 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXpicture.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/picture.c,v 1.30 2003/01/26 16:40:43 eich Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "NXpicturestr.h" + +#include "Screen.h" +#include "Pixmaps.h" +#include "Drawable.h" + +void *nxagentMatchingFormats(PictFormatPtr pForm); + +int PictureScreenPrivateIndex = -1; +int PictureWindowPrivateIndex; +int PictureGeneration; +RESTYPE PictureType; +RESTYPE PictFormatType; +RESTYPE GlyphSetType; +int PictureCmapPolicy = PictureCmapPolicyDefault; + +Bool +PictureDestroyWindow (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + + while ((pPicture = GetPictureWindow(pWindow))) + { + SetPictureWindow(pWindow, pPicture->pNext); + if (pPicture->id) + FreeResource (pPicture->id, PictureType); + FreePicture ((pointer) pPicture, pPicture->id); + } + pScreen->DestroyWindow = ps->DestroyWindow; + ret = (*pScreen->DestroyWindow) (pWindow); + ps->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = PictureDestroyWindow; + return ret; +} + +Bool +PictureCloseScreen (int index, ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + int n; + + pScreen->CloseScreen = ps->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + PictureResetFilters (pScreen); + for (n = 0; n < ps->nformats; n++) + if (ps->formats[n].type == PictTypeIndexed) + (*ps->CloseIndexed) (pScreen, &ps->formats[n]); + SetPictureScreen(pScreen, 0); + xfree (ps->formats); + xfree (ps); + return ret; +} + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + pScreen->StoreColors = ps->StoreColors; + (*pScreen->StoreColors) (pColormap, ndef, pdef); + ps->StoreColors = pScreen->StoreColors; + pScreen->StoreColors = PictureStoreColors; + + if (pColormap->class == PseudoColor || pColormap->class == GrayScale) + { + PictFormatPtr format = ps->formats; + int nformats = ps->nformats; + + while (nformats--) + { + if (format->type == PictTypeIndexed && + format->index.pColormap == pColormap) + { + (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); + break; + } + format++; + } + } +} + +static int +visualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + int d, v; + DepthPtr pDepth; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + return 0; +} + +typedef struct _formatInit { + CARD32 format; + CARD8 depth; +} FormatInitRec, *FormatInitPtr; + +static int +addFormat (FormatInitRec formats[256], + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + formats[nformat].format = format; + formats[nformat].depth = depth; + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) +{ +#ifdef NXAGENT_SERVER + int nformats, f, n; +#else + int nformats, f; +#endif + PictFormatPtr pFormats; + FormatInitRec formats[1024]; + CARD32 format; + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int type; + int r, g, b; + int d; + DepthPtr pDepth; + + nformats = 0; + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + formats[nformats].format = PICT_x8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + bpp = BitsPerPixel (depth); + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + type = PICT_TYPE_OTHER; + /* + * Current rendering code supports only two direct formats, + * fields must be packed together at the bottom of the pixel + * and must be either RGB or BGR + */ + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + type = PICT_TYPE_ARGB; + } + else if (pVisual->offsetRed == 0 && + pVisual->offsetGreen == r && + pVisual->offsetBlue == r + g) + { + type = PICT_TYPE_ABGR; + } + if (type != PICT_TYPE_OTHER) + { + format = PICT_FORMAT(bpp, type, 0, r, g, b); + nformats = addFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); + nformats = addFormat (formats, nformats, format, depth); + break; + case StaticGray: + case GrayScale: + format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); + nformats = addFormat (formats, nformats, format, depth); + break; + } + } + /* + * Walk supported depths and add useful Direct formats + */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + switch (bpp) { + case 16: + /* depth 12 formats */ + if (pDepth->depth >= 12) + { + nformats = addFormat (formats, nformats, + PICT_x4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x4b4g4r4, pDepth->depth); + } + /* depth 15 formats */ + if (pDepth->depth >= 15) + { + nformats = addFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x1b5g5r5, pDepth->depth); + } + /* depth 16 formats */ + if (pDepth->depth >= 16) + { + nformats = addFormat (formats, nformats, + PICT_a1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a1b5g5r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b5g6r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4b4g4r4, pDepth->depth); + } + break; + case 24: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b8g8r8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x8b8g8r8, pDepth->depth); + } + break; + } + } + + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); +#ifdef NXAGENT_SERVER + for (f = 0, n = 0; n < nformats; n++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[n].depth; + format = formats[n].format; + pFormats[f].format = format; +#else + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; +#endif + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_ARGB: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = (PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_B(format); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = 0; + break; + + case PICT_TYPE_ABGR: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = (PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_R(format); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = 0; + break; + + case PICT_TYPE_A: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + + /* remaining fields already set to zero */ + break; + + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + pFormats[f].type = PictTypeIndexed; + pFormats[f].index.pVisual = &pScreen->visuals[PICT_FORMAT_VIS(format)]; + break; + } + +#ifdef NXAGENT_SERVER + if (nxagentMatchingFormats(&pFormats[f]) != NULL) + { + f++; + } + else + { + memset(&pFormats[f], '\0', sizeof(PictFormatRec)); + } + } + *nformatp = f; +#else + } + *nformatp = nformats; +#endif + return pFormats; +} + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return FALSE; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->type == PictTypeIndexed && !format->index.pColormap) + { + if (format->index.pVisual->vid == pScreen->rootVisual) + format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + else + { + if (CreateColormap (FakeClientID (0), pScreen, + format->index.pVisual, + &format->index.pColormap, AllocNone, + 0) != Success) + { + return FALSE; + } + } + if (!(*ps->InitIndexed) (pScreen, format)) + return FALSE; + } + format++; + } + return TRUE; +} + +Bool +PictureFinishInit (void) +{ + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + { + if (!PictureInitIndexedFormats (screenInfo.screens[s])) + return FALSE; + (void) AnimCurInit (screenInfo.screens[s]); + } + + return TRUE; +} + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return FALSE; + ps->subpixel = subpixel; + return TRUE; + +} + +int +PictureGetSubpixelOrder (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return SubPixelUnknown; + return ps->subpixel; +} + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + int type; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + switch (pVisual->class) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + type = PictTypeIndexed; + break; + case TrueColor: + type = PictTypeDirect; + break; + case DirectColor: + default: + return 0; + } + while (nformat--) + { + if (format->depth == depth && format->type == type) + { + if (type == PictTypeIndexed) + { + if (format->index.pVisual == pVisual) + return format; + } + else + { + if (format->direct.redMask << format->direct.red == + pVisual->redMask && + format->direct.greenMask << format->direct.green == + pVisual->greenMask && + format->direct.blueMask << format->direct.blue == + pVisual->blueMask) + { + return format; + } + } + } + format++; + } + return 0; +} + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->depth == depth && format->format == (f & 0xffffff)) + return format; + format++; + } + return 0; +} + +int +PictureParseCmapPolicy (const char *name) +{ + if ( strcmp (name, "default" ) == 0) + return PictureCmapPolicyDefault; + else if ( strcmp (name, "mono" ) == 0) + return PictureCmapPolicyMono; + else if ( strcmp (name, "gray" ) == 0) + return PictureCmapPolicyGray; + else if ( strcmp (name, "color" ) == 0) + return PictureCmapPolicyColor; + else if ( strcmp (name, "all" ) == 0) + return PictureCmapPolicyAll; + else + return PictureCmapPolicyInvalid; +} + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + int n; + CARD32 type, a, r, g, b; + + if (PictureGeneration != serverGeneration) + { + PictureType = CreateNewResourceType (FreePicture); + if (!PictureType) + return FALSE; + PictFormatType = CreateNewResourceType (FreePictFormat); + if (!PictFormatType) + return FALSE; + GlyphSetType = CreateNewResourceType (FreeGlyphSet); + if (!GlyphSetType) + return FALSE; + PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (PictureScreenPrivateIndex < 0) + return FALSE; + PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); + PictureGeneration = serverGeneration; +#ifdef XResExtension + RegisterResourceName (PictureType, "PICTURE"); + RegisterResourceName (PictFormatType, "PICTFORMAT"); + RegisterResourceName (GlyphSetType, "GLYPHSET"); +#endif + } + if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) + return FALSE; + + if (!formats) + { + formats = PictureCreateDefaultFormats (pScreen, &nformats); + if (!formats) + return FALSE; + } + for (n = 0; n < nformats; n++) + { + if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) + { + xfree (formats); + return FALSE; + } + if (formats[n].type == PictTypeIndexed) + { + if ((formats[n].index.pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); + if (!ps) + { + xfree (formats); + return FALSE; + } + SetPictureScreen(pScreen, ps); + if (!GlyphInit (pScreen)) + { + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + ps->totalPictureSize = sizeof (PictureRec); + ps->PicturePrivateSizes = 0; + ps->PicturePrivateLen = 0; + + ps->formats = formats; + ps->fallback = formats; + ps->nformats = nformats; + + ps->filters = 0; + ps->nfilters = 0; + ps->filterAliases = 0; + ps->nfilterAliases = 0; + + ps->subpixel = SubPixelUnknown; + + ps->CloseScreen = pScreen->CloseScreen; + ps->DestroyWindow = pScreen->DestroyWindow; + ps->StoreColors = pScreen->StoreColors; + pScreen->DestroyWindow = PictureDestroyWindow; + pScreen->CloseScreen = PictureCloseScreen; + pScreen->StoreColors = PictureStoreColors; + + if (!PictureSetDefaultFilters (pScreen)) + { + PictureResetFilters (pScreen); + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + return TRUE; +} + +void +SetPictureToDefaults (PicturePtr pPicture) +{ + pPicture->refcnt = 1; + pPicture->repeat = 0; + pPicture->graphicsExposures = FALSE; + pPicture->subWindowMode = ClipByChildren; + pPicture->polyEdge = PolyEdgeSharp; + pPicture->polyMode = PolyModePrecise; + pPicture->freeCompClip = FALSE; + pPicture->clientClipType = CT_NONE; + pPicture->componentAlpha = FALSE; + + pPicture->alphaMap = 0; + pPicture->alphaOrigin.x = 0; + pPicture->alphaOrigin.y = 0; + + pPicture->clipOrigin.x = 0; + pPicture->clipOrigin.y = 0; + pPicture->clientClip = 0; + + pPicture->transform = 0; + + pPicture->dither = None; + pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); + pPicture->filter_params = 0; + pPicture->filter_nparams = 0; + + pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; + pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; +} + +PicturePtr +AllocatePicture (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture; + char *ptr; + DevUnion *ppriv; + unsigned int *sizes; + unsigned int size; + int i; + + pPicture = (PicturePtr) xalloc (ps->totalPictureSize); + if (!pPicture) + return 0; + ppriv = (DevUnion *)(pPicture + 1); + pPicture->devPrivates = ppriv; + sizes = ps->PicturePrivateSizes; + ptr = (char *)(ppriv + ps->PicturePrivateLen); + for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return pPicture; +} + +/* + * Let picture always point to the virtual pixmap. + * For sure this is not the best way to deal with + * the virtual frame-buffer. + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask vmask, + XID *vlist, + ClientPtr client, + int *error) +{ + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); + + pPicture = AllocatePicture (pDrawable->pScreen); + if (!pPicture) + { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pDrawable = pDrawable; + pPicture->pFormat = pFormat; + pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); + if (pDrawable->type == DRAWABLE_PIXMAP) + { + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + pPicture->pDrawable = nxagentVirtualDrawable(pDrawable); + + #endif + + ++((PixmapPtr)pDrawable)->refcnt; + pPicture->pNext = 0; + } + else + { + pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); + SetPictureWindow(((WindowPtr) pDrawable), pPicture); + } + + SetPictureToDefaults (pPicture); + + if (vmask) + *error = ChangePicture (pPicture, vmask, vlist, 0, client); + else + *error = Success; + if (*error == Success) + *error = (*ps->CreatePicture) (pPicture); + if (*error != Success) + { + FreePicture (pPicture, (XID) 0); + pPicture = 0; + } + return pPicture; +} + +#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) + +#define NEXT_PTR(_type) ((_type) ulist++->ptr) + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BITS32 index2; + int error = 0; + BITS32 maskQ; + + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + maskQ = vmask; + while (vmask && !error) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + pPicture->stateChanges |= index2; + switch (index2) + { + case CPRepeat: + { + unsigned int newr; + newr = NEXT_VAL(unsigned int); + if (newr <= xTrue) + pPicture->repeat = newr; + else + { + client->errorValue = newr; + error = BadValue; + } + } + break; + case CPAlphaMap: + { + PicturePtr pAlpha; + + if (vlist) + { + Picture pid = NEXT_VAL(Picture); + + if (pid == None) + pAlpha = 0; + else + { + pAlpha = (PicturePtr) SecurityLookupIDByType(client, + pid, + PictureType, + SecurityWriteAccess|SecurityReadAccess); + if (!pAlpha) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + if (pAlpha->pDrawable->type != DRAWABLE_PIXMAP) + { + client->errorValue = pid; + error = BadMatch; + break; + } + } + } + else + pAlpha = NEXT_PTR(PicturePtr); + if (!error) + { + if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) + pAlpha->refcnt++; + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + pPicture->alphaMap = pAlpha; + } + } + break; + case CPAlphaXOrigin: + pPicture->alphaOrigin.x = NEXT_VAL(INT16); + break; + case CPAlphaYOrigin: + pPicture->alphaOrigin.y = NEXT_VAL(INT16); + break; + case CPClipXOrigin: + pPicture->clipOrigin.x = NEXT_VAL(INT16); + break; + case CPClipYOrigin: + pPicture->clipOrigin.y = NEXT_VAL(INT16); + break; + case CPClipMask: + { + Pixmap pid; + PixmapPtr pPixmap; + int clipType; + + if (vlist) + { + pid = NEXT_VAL(Pixmap); + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + { + clipType = CT_PIXMAP; + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + } + } + else + { + pPixmap = NEXT_PTR(PixmapPtr); + if (pPixmap) + clipType = CT_PIXMAP; + else + clipType = CT_NONE; + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + break; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + error = (*ps->ChangePictureClip)(pPicture, clipType, + (pointer)pPixmap, 0); + break; + } + case CPGraphicsExposure: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe <= xTrue) + pPicture->graphicsExposures = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPSubwindowMode: + { + unsigned int news; + news = NEXT_VAL(unsigned int); + if (news == ClipByChildren || news == IncludeInferiors) + pPicture->subWindowMode = news; + else + { + client->errorValue = news; + error = BadValue; + } + } + break; + case CPPolyEdge: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) + pPicture->polyEdge = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPPolyMode: + { + unsigned int newm; + newm = NEXT_VAL(unsigned int); + if (newm == PolyModePrecise || newm == PolyModeImprecise) + pPicture->polyMode = newm; + else + { + client->errorValue = newm; + error = BadValue; + } + } + break; + case CPDither: + pPicture->dither = NEXT_VAL(Atom); + break; + case CPComponentAlpha: + { + unsigned int newca; + + newca = NEXT_VAL (unsigned int); + if (newca <= xTrue) + pPicture->componentAlpha = newca; + else + { + client->errorValue = newca; + error = BadValue; + } + } + break; + default: + client->errorValue = maskQ; + error = BadValue; + break; + } + } + (*ps->ChangePicture) (pPicture, maskQ); + return error; +} + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + + clientClip = RECTS_TO_REGION(pScreen, + nRect, rects, CT_UNSORTED); + if (!clientClip) + return BadAlloc; + result =(*ps->ChangePictureClip) (pPicture, CT_REGION, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + static const PictTransform identity = { { + { xFixed1, 0x00000, 0x00000 }, + { 0x00000, xFixed1, 0x00000 }, + { 0x00000, 0x00000, xFixed1 }, + } }; + + if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0) + transform = 0; + + if (transform) + { + if (!pPicture->transform) + { + pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); + if (!pPicture->transform) + return BadAlloc; + } + *pPicture->transform = *transform; + } + else + { + if (pPicture->transform) + { + xfree (pPicture->transform); + pPicture->transform = 0; + } + } + return Success; +} + +static void +ValidateOnePicture (PicturePtr pPicture) +{ + if (pPicture->serialNumber != pPicture->pDrawable->serialNumber) + { + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); + pPicture->stateChanges = 0; + pPicture->serialNumber = pPicture->pDrawable->serialNumber; + } +} + +void +ValidatePicture(PicturePtr pPicture) +{ + ValidateOnePicture (pPicture); + if (pPicture->alphaMap) + ValidateOnePicture (pPicture->alphaMap); +} + +int +FreePicture (pointer value, + XID pid) +{ + PicturePtr pPicture = (PicturePtr) value; + + if (--pPicture->refcnt == 0) + { + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + (*ps->DestroyPicture) (pPicture); + (*ps->DestroyPictureClip) (pPicture); + if (pPicture->transform) + xfree (pPicture->transform); + if (pPicture->pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PicturePtr *pPrev; + + for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); + *pPrev; + pPrev = &(*pPrev)->pNext) + { + if (*pPrev == pPicture) + { + *pPrev = pPicture->pNext; + break; + } + } + } + else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) + { + (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); + } + xfree (pPicture); + } + return Success; +} + +int +FreePictFormat (pointer pPictFormat, + XID pid) +{ + return Success; +} + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); +} + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + + #ifdef TEST + fprintf(stderr, "CompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); +} + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pDst); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); +} + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); +} + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); +} + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +typedef xFixed_32_32 xFixed_48_16; + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + for (j = 0; j < 2; j++) + { + partial = (xFixed_48_16) result.vector[j] << 16; + v = partial / result.vector[2]; + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + vector->vector[j] = (xFixed) v; + } + vector->vector[2] = xFixed1; + return TRUE; +} + +#ifndef True +# define True 1 +#endif + +#ifndef False +# define False 0 +#endif + +void nxagentReconnectPictFormat(void*, XID, void*); + +Bool nxagentReconnectAllPictFormat(void *p) +{ + PictFormatPtr formats_old, formats; + int nformats, nformats_old; + Bool success = True; + Bool matched; + int i, n; + CARD32 type, a, r, g, b; + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectAllPictFormat\n"); + #endif + + formats_old = GetPictureScreen(nxagentDefaultScreen) -> formats; + nformats_old = GetPictureScreen(nxagentDefaultScreen) -> nformats; + + /* + * TODO: We could copy PictureCreateDefaultFormats, + * in order not to waste ID with FakeClientID(). + */ + formats = PictureCreateDefaultFormats (nxagentDefaultScreen, &nformats); + + if (!formats) + return FALSE; + + for (n = 0; n < nformats; n++) + { + if (formats[n].type == PictTypeIndexed) + { + if ((formats[n].index.pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + + for (n = 0; n < nformats_old; n++) + { + for (i = 0, matched = False; (!matched) && (i < nformats); i++) + { + if (formats_old[n].format == formats[i].format && + formats_old[n].type == formats[i].type && + formats_old[n].direct.red == formats[i].direct.red && + formats_old[n].direct.green == formats[i].direct.green && + formats_old[n].direct.blue == formats[i].direct.blue && + formats_old[n].direct.redMask == formats[i].direct.redMask && + formats_old[n].direct.greenMask == formats[i].direct.greenMask && + formats_old[n].direct.blueMask == formats[i].direct.blueMask && + formats_old[n].direct.alpha == formats[i].direct.alpha && + formats_old[n].direct.alphaMask == formats[i].direct.alphaMask) + { + /* + * Regard depth 16 and 15 as were the same, if all other values match. + */ + + if ((formats_old[n].depth == formats[i].depth) || + ((formats_old[n].depth == 15 || formats_old[n].depth == 16) && + (formats[i].depth == 15 || formats[i].depth == 16))) + { + matched = True; + } + } + } + if (!matched) + return False; + } + xfree(formats); + + /* TODO: Perhaps do i have to do PictureFinishInit ?. */ + /* TODO: We have to check for new Render protocol version. */ + + for (i = 0; (i < MAXCLIENTS) && (success); i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], PictFormatType, nxagentReconnectPictFormat, &success); + } + } + + return success; +} + +/* + * It seem we don't have nothing + * to do for reconnect PictureFormat. + */ + +void nxagentReconnectPictFormat(void *p0, XID x1, void *p2) +{ + PictFormatPtr pFormat; + Bool *pBool; + + pFormat = (PictFormatPtr)p0; + pBool = (Bool*)p2; + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectPictFormat.\n"); + #endif +} + + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.XF86.original new file mode 100644 index 000000000..b2ef69bdf --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.XF86.original @@ -0,0 +1,1305 @@ +/* + * $XFree86: xc/programs/Xserver/render/picture.c,v 1.30 2003/01/26 16:40:43 eich Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" + +int PictureScreenPrivateIndex = -1; +int PictureWindowPrivateIndex; +int PictureGeneration; +RESTYPE PictureType; +RESTYPE PictFormatType; +RESTYPE GlyphSetType; +int PictureCmapPolicy = PictureCmapPolicyDefault; + +Bool +PictureDestroyWindow (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + + while ((pPicture = GetPictureWindow(pWindow))) + { + SetPictureWindow(pWindow, pPicture->pNext); + if (pPicture->id) + FreeResource (pPicture->id, PictureType); + FreePicture ((pointer) pPicture, pPicture->id); + } + pScreen->DestroyWindow = ps->DestroyWindow; + ret = (*pScreen->DestroyWindow) (pWindow); + ps->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = PictureDestroyWindow; + return ret; +} + +Bool +PictureCloseScreen (int index, ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + int n; + + pScreen->CloseScreen = ps->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + PictureResetFilters (pScreen); + for (n = 0; n < ps->nformats; n++) + if (ps->formats[n].type == PictTypeIndexed) + (*ps->CloseIndexed) (pScreen, &ps->formats[n]); + SetPictureScreen(pScreen, 0); + xfree (ps->formats); + xfree (ps); + return ret; +} + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + pScreen->StoreColors = ps->StoreColors; + (*pScreen->StoreColors) (pColormap, ndef, pdef); + ps->StoreColors = pScreen->StoreColors; + pScreen->StoreColors = PictureStoreColors; + + if (pColormap->class == PseudoColor || pColormap->class == GrayScale) + { + PictFormatPtr format = ps->formats; + int nformats = ps->nformats; + + while (nformats--) + { + if (format->type == PictTypeIndexed && + format->index.pColormap == pColormap) + { + (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); + break; + } + format++; + } + } +} + +static int +visualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + int d, v; + DepthPtr pDepth; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + return 0; +} + +typedef struct _formatInit { + CARD32 format; + CARD8 depth; +} FormatInitRec, *FormatInitPtr; + +static int +addFormat (FormatInitRec formats[256], + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + formats[nformat].format = format; + formats[nformat].depth = depth; + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) +{ + int nformats, f; + PictFormatPtr pFormats; + FormatInitRec formats[1024]; + CARD32 format; + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int type; + int r, g, b; + int d; + DepthPtr pDepth; + + nformats = 0; + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + formats[nformats].format = PICT_x8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + bpp = BitsPerPixel (depth); + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + type = PICT_TYPE_OTHER; + /* + * Current rendering code supports only two direct formats, + * fields must be packed together at the bottom of the pixel + * and must be either RGB or BGR + */ + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + type = PICT_TYPE_ARGB; + } + else if (pVisual->offsetRed == 0 && + pVisual->offsetGreen == r && + pVisual->offsetBlue == r + g) + { + type = PICT_TYPE_ABGR; + } + if (type != PICT_TYPE_OTHER) + { + format = PICT_FORMAT(bpp, type, 0, r, g, b); + nformats = addFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); + nformats = addFormat (formats, nformats, format, depth); + break; + case StaticGray: + case GrayScale: + format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); + nformats = addFormat (formats, nformats, format, depth); + break; + } + } + /* + * Walk supported depths and add useful Direct formats + */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + switch (bpp) { + case 16: + /* depth 12 formats */ + if (pDepth->depth >= 12) + { + nformats = addFormat (formats, nformats, + PICT_x4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x4b4g4r4, pDepth->depth); + } + /* depth 15 formats */ + if (pDepth->depth >= 15) + { + nformats = addFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x1b5g5r5, pDepth->depth); + } + /* depth 16 formats */ + if (pDepth->depth >= 16) + { + nformats = addFormat (formats, nformats, + PICT_a1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a1b5g5r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b5g6r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4b4g4r4, pDepth->depth); + } + break; + case 24: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b8g8r8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x8b8g8r8, pDepth->depth); + } + break; + } + } + + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_ARGB: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = (PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_B(format); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = 0; + break; + + case PICT_TYPE_ABGR: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = (PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_R(format); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = 0; + break; + + case PICT_TYPE_A: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + + /* remaining fields already set to zero */ + break; + + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + pFormats[f].type = PictTypeIndexed; + pFormats[f].index.pVisual = &pScreen->visuals[PICT_FORMAT_VIS(format)]; + break; + } + } + *nformatp = nformats; + return pFormats; +} + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return FALSE; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->type == PictTypeIndexed && !format->index.pColormap) + { + if (format->index.pVisual->vid == pScreen->rootVisual) + format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + else + { + if (CreateColormap (FakeClientID (0), pScreen, + format->index.pVisual, + &format->index.pColormap, AllocNone, + 0) != Success) + { + return FALSE; + } + } + if (!(*ps->InitIndexed) (pScreen, format)) + return FALSE; + } + format++; + } + return TRUE; +} + +Bool +PictureFinishInit (void) +{ + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + { + if (!PictureInitIndexedFormats (screenInfo.screens[s])) + return FALSE; + (void) AnimCurInit (screenInfo.screens[s]); + } + + return TRUE; +} + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return FALSE; + ps->subpixel = subpixel; + return TRUE; + +} + +int +PictureGetSubpixelOrder (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return SubPixelUnknown; + return ps->subpixel; +} + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + int type; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + switch (pVisual->class) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + type = PictTypeIndexed; + break; + case TrueColor: + type = PictTypeDirect; + break; + case DirectColor: + default: + return 0; + } + while (nformat--) + { + if (format->depth == depth && format->type == type) + { + if (type == PictTypeIndexed) + { + if (format->index.pVisual == pVisual) + return format; + } + else + { + if (format->direct.redMask << format->direct.red == + pVisual->redMask && + format->direct.greenMask << format->direct.green == + pVisual->greenMask && + format->direct.blueMask << format->direct.blue == + pVisual->blueMask) + { + return format; + } + } + } + format++; + } + return 0; +} + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->depth == depth && format->format == (f & 0xffffff)) + return format; + format++; + } + return 0; +} + +int +PictureParseCmapPolicy (const char *name) +{ + if ( strcmp (name, "default" ) == 0) + return PictureCmapPolicyDefault; + else if ( strcmp (name, "mono" ) == 0) + return PictureCmapPolicyMono; + else if ( strcmp (name, "gray" ) == 0) + return PictureCmapPolicyGray; + else if ( strcmp (name, "color" ) == 0) + return PictureCmapPolicyColor; + else if ( strcmp (name, "all" ) == 0) + return PictureCmapPolicyAll; + else + return PictureCmapPolicyInvalid; +} + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + int n; + CARD32 type, a, r, g, b; + + if (PictureGeneration != serverGeneration) + { + PictureType = CreateNewResourceType (FreePicture); + if (!PictureType) + return FALSE; + PictFormatType = CreateNewResourceType (FreePictFormat); + if (!PictFormatType) + return FALSE; + GlyphSetType = CreateNewResourceType (FreeGlyphSet); + if (!GlyphSetType) + return FALSE; + PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (PictureScreenPrivateIndex < 0) + return FALSE; + PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); + PictureGeneration = serverGeneration; +#ifdef XResExtension + RegisterResourceName (PictureType, "PICTURE"); + RegisterResourceName (PictFormatType, "PICTFORMAT"); + RegisterResourceName (GlyphSetType, "GLYPHSET"); +#endif + } + if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) + return FALSE; + + if (!formats) + { + formats = PictureCreateDefaultFormats (pScreen, &nformats); + if (!formats) + return FALSE; + } + for (n = 0; n < nformats; n++) + { + if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) + { + xfree (formats); + return FALSE; + } + if (formats[n].type == PictTypeIndexed) + { + if ((formats[n].index.pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); + if (!ps) + { + xfree (formats); + return FALSE; + } + SetPictureScreen(pScreen, ps); + if (!GlyphInit (pScreen)) + { + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + ps->totalPictureSize = sizeof (PictureRec); + ps->PicturePrivateSizes = 0; + ps->PicturePrivateLen = 0; + + ps->formats = formats; + ps->fallback = formats; + ps->nformats = nformats; + + ps->filters = 0; + ps->nfilters = 0; + ps->filterAliases = 0; + ps->nfilterAliases = 0; + + ps->subpixel = SubPixelUnknown; + + ps->CloseScreen = pScreen->CloseScreen; + ps->DestroyWindow = pScreen->DestroyWindow; + ps->StoreColors = pScreen->StoreColors; + pScreen->DestroyWindow = PictureDestroyWindow; + pScreen->CloseScreen = PictureCloseScreen; + pScreen->StoreColors = PictureStoreColors; + + if (!PictureSetDefaultFilters (pScreen)) + { + PictureResetFilters (pScreen); + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + return TRUE; +} + +void +SetPictureToDefaults (PicturePtr pPicture) +{ + pPicture->refcnt = 1; + pPicture->repeat = 0; + pPicture->graphicsExposures = FALSE; + pPicture->subWindowMode = ClipByChildren; + pPicture->polyEdge = PolyEdgeSharp; + pPicture->polyMode = PolyModePrecise; + pPicture->freeCompClip = FALSE; + pPicture->clientClipType = CT_NONE; + pPicture->componentAlpha = FALSE; + + pPicture->alphaMap = 0; + pPicture->alphaOrigin.x = 0; + pPicture->alphaOrigin.y = 0; + + pPicture->clipOrigin.x = 0; + pPicture->clipOrigin.y = 0; + pPicture->clientClip = 0; + + pPicture->transform = 0; + + pPicture->dither = None; + pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); + pPicture->filter_params = 0; + pPicture->filter_nparams = 0; + + pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; + pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; +} + +PicturePtr +AllocatePicture (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture; + char *ptr; + DevUnion *ppriv; + unsigned int *sizes; + unsigned int size; + int i; + + pPicture = (PicturePtr) xalloc (ps->totalPictureSize); + if (!pPicture) + return 0; + ppriv = (DevUnion *)(pPicture + 1); + pPicture->devPrivates = ppriv; + sizes = ps->PicturePrivateSizes; + ptr = (char *)(ppriv + ps->PicturePrivateLen); + for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return pPicture; +} + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask vmask, + XID *vlist, + ClientPtr client, + int *error) +{ + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); + + pPicture = AllocatePicture (pDrawable->pScreen); + if (!pPicture) + { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pDrawable = pDrawable; + pPicture->pFormat = pFormat; + pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); + if (pDrawable->type == DRAWABLE_PIXMAP) + { + ++((PixmapPtr)pDrawable)->refcnt; + pPicture->pNext = 0; + } + else + { + pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); + SetPictureWindow(((WindowPtr) pDrawable), pPicture); + } + + SetPictureToDefaults (pPicture); + + if (vmask) + *error = ChangePicture (pPicture, vmask, vlist, 0, client); + else + *error = Success; + if (*error == Success) + *error = (*ps->CreatePicture) (pPicture); + if (*error != Success) + { + FreePicture (pPicture, (XID) 0); + pPicture = 0; + } + return pPicture; +} + +#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) + +#define NEXT_PTR(_type) ((_type) ulist++->ptr) + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BITS32 index2; + int error = 0; + BITS32 maskQ; + + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + maskQ = vmask; + while (vmask && !error) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + pPicture->stateChanges |= index2; + switch (index2) + { + case CPRepeat: + { + unsigned int newr; + newr = NEXT_VAL(unsigned int); + if (newr <= xTrue) + pPicture->repeat = newr; + else + { + client->errorValue = newr; + error = BadValue; + } + } + break; + case CPAlphaMap: + { + PicturePtr pAlpha; + + if (vlist) + { + Picture pid = NEXT_VAL(Picture); + + if (pid == None) + pAlpha = 0; + else + { + pAlpha = (PicturePtr) SecurityLookupIDByType(client, + pid, + PictureType, + SecurityWriteAccess|SecurityReadAccess); + if (!pAlpha) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + if (pAlpha->pDrawable->type != DRAWABLE_PIXMAP) + { + client->errorValue = pid; + error = BadMatch; + break; + } + } + } + else + pAlpha = NEXT_PTR(PicturePtr); + if (!error) + { + if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) + pAlpha->refcnt++; + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + pPicture->alphaMap = pAlpha; + } + } + break; + case CPAlphaXOrigin: + pPicture->alphaOrigin.x = NEXT_VAL(INT16); + break; + case CPAlphaYOrigin: + pPicture->alphaOrigin.y = NEXT_VAL(INT16); + break; + case CPClipXOrigin: + pPicture->clipOrigin.x = NEXT_VAL(INT16); + break; + case CPClipYOrigin: + pPicture->clipOrigin.y = NEXT_VAL(INT16); + break; + case CPClipMask: + { + Pixmap pid; + PixmapPtr pPixmap; + int clipType; + + if (vlist) + { + pid = NEXT_VAL(Pixmap); + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + { + clipType = CT_PIXMAP; + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + } + } + else + { + pPixmap = NEXT_PTR(PixmapPtr); + if (pPixmap) + clipType = CT_PIXMAP; + else + clipType = CT_NONE; + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + break; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + error = (*ps->ChangePictureClip)(pPicture, clipType, + (pointer)pPixmap, 0); + break; + } + case CPGraphicsExposure: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe <= xTrue) + pPicture->graphicsExposures = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPSubwindowMode: + { + unsigned int news; + news = NEXT_VAL(unsigned int); + if (news == ClipByChildren || news == IncludeInferiors) + pPicture->subWindowMode = news; + else + { + client->errorValue = news; + error = BadValue; + } + } + break; + case CPPolyEdge: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) + pPicture->polyEdge = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPPolyMode: + { + unsigned int newm; + newm = NEXT_VAL(unsigned int); + if (newm == PolyModePrecise || newm == PolyModeImprecise) + pPicture->polyMode = newm; + else + { + client->errorValue = newm; + error = BadValue; + } + } + break; + case CPDither: + pPicture->dither = NEXT_VAL(Atom); + break; + case CPComponentAlpha: + { + unsigned int newca; + + newca = NEXT_VAL (unsigned int); + if (newca <= xTrue) + pPicture->componentAlpha = newca; + else + { + client->errorValue = newca; + error = BadValue; + } + } + break; + default: + client->errorValue = maskQ; + error = BadValue; + break; + } + } + (*ps->ChangePicture) (pPicture, maskQ); + return error; +} + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + + clientClip = RECTS_TO_REGION(pScreen, + nRect, rects, CT_UNSORTED); + if (!clientClip) + return BadAlloc; + result =(*ps->ChangePictureClip) (pPicture, CT_REGION, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + static const PictTransform identity = { { + { xFixed1, 0x00000, 0x00000 }, + { 0x00000, xFixed1, 0x00000 }, + { 0x00000, 0x00000, xFixed1 }, + } }; + + if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0) + transform = 0; + + if (transform) + { + if (!pPicture->transform) + { + pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); + if (!pPicture->transform) + return BadAlloc; + } + *pPicture->transform = *transform; + } + else + { + if (pPicture->transform) + { + xfree (pPicture->transform); + pPicture->transform = 0; + } + } + return Success; +} + +static void +ValidateOnePicture (PicturePtr pPicture) +{ + if (pPicture->serialNumber != pPicture->pDrawable->serialNumber) + { + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); + pPicture->stateChanges = 0; + pPicture->serialNumber = pPicture->pDrawable->serialNumber; + } +} + +void +ValidatePicture(PicturePtr pPicture) +{ + ValidateOnePicture (pPicture); + if (pPicture->alphaMap) + ValidateOnePicture (pPicture->alphaMap); +} + +int +FreePicture (pointer value, + XID pid) +{ + PicturePtr pPicture = (PicturePtr) value; + + if (--pPicture->refcnt == 0) + { + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + (*ps->DestroyPicture) (pPicture); + (*ps->DestroyPictureClip) (pPicture); + if (pPicture->transform) + xfree (pPicture->transform); + if (pPicture->pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PicturePtr *pPrev; + + for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); + *pPrev; + pPrev = &(*pPrev)->pNext) + { + if (*pPrev == pPicture) + { + *pPrev = pPicture->pNext; + break; + } + } + } + else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) + { + (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); + } + xfree (pPicture); + } + return Success; +} + +int +FreePictFormat (pointer pPictFormat, + XID pid) +{ + return Success; +} + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); +} + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); +} + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pDst); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); +} + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); +} + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); +} + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +typedef xFixed_32_32 xFixed_48_16; + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + for (j = 0; j < 2; j++) + { + partial = (xFixed_48_16) result.vector[j] << 16; + v = partial / result.vector[2]; + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + vector->vector[j] = (xFixed) v; + } + vector->vector[2] = xFixed1; + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h new file mode 100644 index 000000000..a1790c3f0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h @@ -0,0 +1,533 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXpicturestr.h" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/picturestr.h,v 1.22 2002/11/23 02:38:15 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original + * picturestr.h or symbols will be redefined. We + * should define a new types and cast when appro- + * priate. + */ + +#ifndef _PICTURESTR_H_ +#define _PICTURESTR_H_ + +#include "NXglyphstr.h" +#include "scrnintstr.h" +#include "resource.h" + +typedef struct _DirectFormat { + CARD16 red, redMask; + CARD16 green, greenMask; + CARD16 blue, blueMask; + CARD16 alpha, alphaMask; +} DirectFormatRec; + +typedef struct _IndexFormat { + VisualPtr pVisual; + ColormapPtr pColormap; + int nvalues; + xIndexValue *pValues; + void *devPrivate; +} IndexFormatRec; + +typedef struct _PictFormat { + CARD32 id; + CARD32 format; /* except bpp */ + unsigned char type; + unsigned char depth; + DirectFormatRec direct; + IndexFormatRec index; +} PictFormatRec; + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + +typedef struct _PictTransform { + xFixed matrix[3][3]; +} PictTransform, *PictTransformPtr; + +typedef struct _Picture { + DrawablePtr pDrawable; + PictFormatPtr pFormat; + CARD32 format; /* PICT_FORMAT */ + int refcnt; + CARD32 id; + PicturePtr pNext; /* chain on same drawable */ + + unsigned int repeat : 1; + unsigned int graphicsExposures : 1; + unsigned int subWindowMode : 1; + unsigned int polyEdge : 1; + unsigned int polyMode : 1; + unsigned int freeCompClip : 1; + unsigned int clientClipType : 2; + unsigned int componentAlpha : 1; + unsigned int unused : 23; + + PicturePtr alphaMap; + DDXPointRec alphaOrigin; + + DDXPointRec clipOrigin; + pointer clientClip; + + Atom dither; + + unsigned long stateChanges; + unsigned long serialNumber; + + RegionPtr pCompositeClip; + + DevUnion *devPrivates; + + PictTransform *transform; + + int filter; + xFixed *filter_params; + int filter_nparams; +} PictureRec; + +typedef struct { + char *name; + xFixed *params; + int nparams; + int id; +} PictFilterRec, *PictFilterPtr; + +#define PictFilterNearest 0 +#define PictFilterBilinear 1 + +#define PictFilterFast 2 +#define PictFilterGood 3 +#define PictFilterBest 4 + +typedef struct { + char *alias; + int alias_id; + int filter_id; +} PictFilterAliasRec, *PictFilterAliasPtr; + +typedef int (*CreatePictureProcPtr) (PicturePtr pPicture); +typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture); +typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture, + int clipType, + pointer value, + int n); +typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture); + +typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture, + PictTransform *transform); + +typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture); + +typedef void (*ChangePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*CompositeProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef void (*GlyphsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs); + +typedef void (*CompositeRectsProcPtr) (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask, + xTrapezoid *trap, + int x_off, + int y_off); + +typedef void (*TrapezoidsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +typedef void (*TrianglesProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +typedef struct _PictureScreen { + int totalPictureSize; + unsigned int *PicturePrivateSizes; + int PicturePrivateLen; + + PictFormatPtr formats; + PictFormatPtr fallback; + int nformats; + + CreatePictureProcPtr CreatePicture; + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + DestroyWindowProcPtr DestroyWindow; + CloseScreenProcPtr CloseScreen; + + StoreColorsProcPtr StoreColors; + + InitIndexedProcPtr InitIndexed; + CloseIndexedProcPtr CloseIndexed; + UpdateIndexedProcPtr UpdateIndexed; + + int subpixel; + + PictFilterPtr filters; + int nfilters; + PictFilterAliasPtr filterAliases; + int nfilterAliases; + + ChangePictureTransformProcPtr ChangePictureTransform; + ChangePictureFilterProcPtr ChangePictureFilter; + DestroyPictureFilterProcPtr DestroyPictureFilter; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; +} PictureScreenRec, *PictureScreenPtr; + +extern int PictureScreenPrivateIndex; +extern int PictureWindowPrivateIndex; +extern RESTYPE PictureType; +extern RESTYPE PictFormatType; +extern RESTYPE GlyphSetType; + +#define GetPictureScreen(s) ((PictureScreenPtr) ((s)->devPrivates[PictureScreenPrivateIndex].ptr)) +#define GetPictureScreenIfSet(s) ((PictureScreenPrivateIndex != -1) ? GetPictureScreen(s) : NULL) +#define SetPictureScreen(s,p) ((s)->devPrivates[PictureScreenPrivateIndex].ptr = (pointer) (p)) +#define GetPictureWindow(w) ((PicturePtr) ((w)->devPrivates[PictureWindowPrivateIndex].ptr)) +#define SetPictureWindow(w,p) ((w)->devPrivates[PictureWindowPrivateIndex].ptr = (pointer) (p)) + +#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, PictureType, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +Bool +PictureDestroyWindow (WindowPtr pWindow); + +Bool +PictureCloseScreen (int Index, ScreenPtr pScreen); + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef); + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen); + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel); + +int +PictureGetSubpixelOrder (ScreenPtr pScreen); + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp); + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual); + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format); + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +int +PictureGetFilterId (char *filter, int len, Bool makeit); + +char * +PictureGetFilterName (int id); + +int +PictureAddFilter (ScreenPtr pScreen, char *filter, xFixed *params, int nparams); + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias); + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen); + +void +PictureResetFilters (ScreenPtr pScreen); + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len); + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams); + +Bool +PictureFinishInit (void); + +void +SetPictureToDefaults (PicturePtr pPicture); + +PicturePtr +AllocatePicture (ScreenPtr pScreen); + +#if 0 +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); +#endif + + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask mask, + XID *list, + ClientPtr client, + int *error); + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client); + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects); + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform); + +void +ValidatePicture(PicturePtr pPicture); + +int +FreePicture (pointer pPicture, + XID pid); + +int +FreePictFormat (pointer pPictFormat, + XID pid); + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs); + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles); + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector); + +void RenderExtensionInit (void); + +Bool +AnimCurInit (ScreenPtr pScreen); + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor); + +#ifdef PANORAMIX +void PanoramiXRenderInit (void); +void PanoramiXRenderReset (void); +#endif + +#endif /* _PICTURESTR_H_ */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.NX.original new file mode 100644 index 000000000..a1790c3f0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.NX.original @@ -0,0 +1,533 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXpicturestr.h" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/picturestr.h,v 1.22 2002/11/23 02:38:15 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original + * picturestr.h or symbols will be redefined. We + * should define a new types and cast when appro- + * priate. + */ + +#ifndef _PICTURESTR_H_ +#define _PICTURESTR_H_ + +#include "NXglyphstr.h" +#include "scrnintstr.h" +#include "resource.h" + +typedef struct _DirectFormat { + CARD16 red, redMask; + CARD16 green, greenMask; + CARD16 blue, blueMask; + CARD16 alpha, alphaMask; +} DirectFormatRec; + +typedef struct _IndexFormat { + VisualPtr pVisual; + ColormapPtr pColormap; + int nvalues; + xIndexValue *pValues; + void *devPrivate; +} IndexFormatRec; + +typedef struct _PictFormat { + CARD32 id; + CARD32 format; /* except bpp */ + unsigned char type; + unsigned char depth; + DirectFormatRec direct; + IndexFormatRec index; +} PictFormatRec; + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + +typedef struct _PictTransform { + xFixed matrix[3][3]; +} PictTransform, *PictTransformPtr; + +typedef struct _Picture { + DrawablePtr pDrawable; + PictFormatPtr pFormat; + CARD32 format; /* PICT_FORMAT */ + int refcnt; + CARD32 id; + PicturePtr pNext; /* chain on same drawable */ + + unsigned int repeat : 1; + unsigned int graphicsExposures : 1; + unsigned int subWindowMode : 1; + unsigned int polyEdge : 1; + unsigned int polyMode : 1; + unsigned int freeCompClip : 1; + unsigned int clientClipType : 2; + unsigned int componentAlpha : 1; + unsigned int unused : 23; + + PicturePtr alphaMap; + DDXPointRec alphaOrigin; + + DDXPointRec clipOrigin; + pointer clientClip; + + Atom dither; + + unsigned long stateChanges; + unsigned long serialNumber; + + RegionPtr pCompositeClip; + + DevUnion *devPrivates; + + PictTransform *transform; + + int filter; + xFixed *filter_params; + int filter_nparams; +} PictureRec; + +typedef struct { + char *name; + xFixed *params; + int nparams; + int id; +} PictFilterRec, *PictFilterPtr; + +#define PictFilterNearest 0 +#define PictFilterBilinear 1 + +#define PictFilterFast 2 +#define PictFilterGood 3 +#define PictFilterBest 4 + +typedef struct { + char *alias; + int alias_id; + int filter_id; +} PictFilterAliasRec, *PictFilterAliasPtr; + +typedef int (*CreatePictureProcPtr) (PicturePtr pPicture); +typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture); +typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture, + int clipType, + pointer value, + int n); +typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture); + +typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture, + PictTransform *transform); + +typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture); + +typedef void (*ChangePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*CompositeProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef void (*GlyphsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs); + +typedef void (*CompositeRectsProcPtr) (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask, + xTrapezoid *trap, + int x_off, + int y_off); + +typedef void (*TrapezoidsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +typedef void (*TrianglesProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +typedef struct _PictureScreen { + int totalPictureSize; + unsigned int *PicturePrivateSizes; + int PicturePrivateLen; + + PictFormatPtr formats; + PictFormatPtr fallback; + int nformats; + + CreatePictureProcPtr CreatePicture; + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + DestroyWindowProcPtr DestroyWindow; + CloseScreenProcPtr CloseScreen; + + StoreColorsProcPtr StoreColors; + + InitIndexedProcPtr InitIndexed; + CloseIndexedProcPtr CloseIndexed; + UpdateIndexedProcPtr UpdateIndexed; + + int subpixel; + + PictFilterPtr filters; + int nfilters; + PictFilterAliasPtr filterAliases; + int nfilterAliases; + + ChangePictureTransformProcPtr ChangePictureTransform; + ChangePictureFilterProcPtr ChangePictureFilter; + DestroyPictureFilterProcPtr DestroyPictureFilter; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; +} PictureScreenRec, *PictureScreenPtr; + +extern int PictureScreenPrivateIndex; +extern int PictureWindowPrivateIndex; +extern RESTYPE PictureType; +extern RESTYPE PictFormatType; +extern RESTYPE GlyphSetType; + +#define GetPictureScreen(s) ((PictureScreenPtr) ((s)->devPrivates[PictureScreenPrivateIndex].ptr)) +#define GetPictureScreenIfSet(s) ((PictureScreenPrivateIndex != -1) ? GetPictureScreen(s) : NULL) +#define SetPictureScreen(s,p) ((s)->devPrivates[PictureScreenPrivateIndex].ptr = (pointer) (p)) +#define GetPictureWindow(w) ((PicturePtr) ((w)->devPrivates[PictureWindowPrivateIndex].ptr)) +#define SetPictureWindow(w,p) ((w)->devPrivates[PictureWindowPrivateIndex].ptr = (pointer) (p)) + +#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, PictureType, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +Bool +PictureDestroyWindow (WindowPtr pWindow); + +Bool +PictureCloseScreen (int Index, ScreenPtr pScreen); + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef); + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen); + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel); + +int +PictureGetSubpixelOrder (ScreenPtr pScreen); + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp); + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual); + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format); + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +int +PictureGetFilterId (char *filter, int len, Bool makeit); + +char * +PictureGetFilterName (int id); + +int +PictureAddFilter (ScreenPtr pScreen, char *filter, xFixed *params, int nparams); + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias); + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen); + +void +PictureResetFilters (ScreenPtr pScreen); + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len); + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams); + +Bool +PictureFinishInit (void); + +void +SetPictureToDefaults (PicturePtr pPicture); + +PicturePtr +AllocatePicture (ScreenPtr pScreen); + +#if 0 +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); +#endif + + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask mask, + XID *list, + ClientPtr client, + int *error); + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client); + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects); + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform); + +void +ValidatePicture(PicturePtr pPicture); + +int +FreePicture (pointer pPicture, + XID pid); + +int +FreePictFormat (pointer pPictFormat, + XID pid); + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs); + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles); + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector); + +void RenderExtensionInit (void); + +Bool +AnimCurInit (ScreenPtr pScreen); + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor); + +#ifdef PANORAMIX +void PanoramiXRenderInit (void); +void PanoramiXRenderReset (void); +#endif + +#endif /* _PICTURESTR_H_ */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.XF86.original new file mode 100644 index 000000000..cb5ea0ac9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.XF86.original @@ -0,0 +1,501 @@ +/* + * $XFree86: xc/programs/Xserver/render/picturestr.h,v 1.22 2002/11/23 02:38:15 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _PICTURESTR_H_ +#define _PICTURESTR_H_ + +#include "glyphstr.h" +#include "scrnintstr.h" +#include "resource.h" + +typedef struct _DirectFormat { + CARD16 red, redMask; + CARD16 green, greenMask; + CARD16 blue, blueMask; + CARD16 alpha, alphaMask; +} DirectFormatRec; + +typedef struct _IndexFormat { + VisualPtr pVisual; + ColormapPtr pColormap; + int nvalues; + xIndexValue *pValues; + void *devPrivate; +} IndexFormatRec; + +typedef struct _PictFormat { + CARD32 id; + CARD32 format; /* except bpp */ + unsigned char type; + unsigned char depth; + DirectFormatRec direct; + IndexFormatRec index; +} PictFormatRec; + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + +typedef struct _PictTransform { + xFixed matrix[3][3]; +} PictTransform, *PictTransformPtr; + +typedef struct _Picture { + DrawablePtr pDrawable; + PictFormatPtr pFormat; + CARD32 format; /* PICT_FORMAT */ + int refcnt; + CARD32 id; + PicturePtr pNext; /* chain on same drawable */ + + unsigned int repeat : 1; + unsigned int graphicsExposures : 1; + unsigned int subWindowMode : 1; + unsigned int polyEdge : 1; + unsigned int polyMode : 1; + unsigned int freeCompClip : 1; + unsigned int clientClipType : 2; + unsigned int componentAlpha : 1; + unsigned int unused : 23; + + PicturePtr alphaMap; + DDXPointRec alphaOrigin; + + DDXPointRec clipOrigin; + pointer clientClip; + + Atom dither; + + unsigned long stateChanges; + unsigned long serialNumber; + + RegionPtr pCompositeClip; + + DevUnion *devPrivates; + + PictTransform *transform; + + int filter; + xFixed *filter_params; + int filter_nparams; +} PictureRec; + +typedef struct { + char *name; + xFixed *params; + int nparams; + int id; +} PictFilterRec, *PictFilterPtr; + +#define PictFilterNearest 0 +#define PictFilterBilinear 1 + +#define PictFilterFast 2 +#define PictFilterGood 3 +#define PictFilterBest 4 + +typedef struct { + char *alias; + int alias_id; + int filter_id; +} PictFilterAliasRec, *PictFilterAliasPtr; + +typedef int (*CreatePictureProcPtr) (PicturePtr pPicture); +typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture); +typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture, + int clipType, + pointer value, + int n); +typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture); + +typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture, + PictTransform *transform); + +typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture); + +typedef void (*ChangePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*CompositeProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef void (*GlyphsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs); + +typedef void (*CompositeRectsProcPtr) (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask, + xTrapezoid *trap, + int x_off, + int y_off); + +typedef void (*TrapezoidsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +typedef void (*TrianglesProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +typedef struct _PictureScreen { + int totalPictureSize; + unsigned int *PicturePrivateSizes; + int PicturePrivateLen; + + PictFormatPtr formats; + PictFormatPtr fallback; + int nformats; + + CreatePictureProcPtr CreatePicture; + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + DestroyWindowProcPtr DestroyWindow; + CloseScreenProcPtr CloseScreen; + + StoreColorsProcPtr StoreColors; + + InitIndexedProcPtr InitIndexed; + CloseIndexedProcPtr CloseIndexed; + UpdateIndexedProcPtr UpdateIndexed; + + int subpixel; + + PictFilterPtr filters; + int nfilters; + PictFilterAliasPtr filterAliases; + int nfilterAliases; + + ChangePictureTransformProcPtr ChangePictureTransform; + ChangePictureFilterProcPtr ChangePictureFilter; + DestroyPictureFilterProcPtr DestroyPictureFilter; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; +} PictureScreenRec, *PictureScreenPtr; + +extern int PictureScreenPrivateIndex; +extern int PictureWindowPrivateIndex; +extern RESTYPE PictureType; +extern RESTYPE PictFormatType; +extern RESTYPE GlyphSetType; + +#define GetPictureScreen(s) ((PictureScreenPtr) ((s)->devPrivates[PictureScreenPrivateIndex].ptr)) +#define GetPictureScreenIfSet(s) ((PictureScreenPrivateIndex != -1) ? GetPictureScreen(s) : NULL) +#define SetPictureScreen(s,p) ((s)->devPrivates[PictureScreenPrivateIndex].ptr = (pointer) (p)) +#define GetPictureWindow(w) ((PicturePtr) ((w)->devPrivates[PictureWindowPrivateIndex].ptr)) +#define SetPictureWindow(w,p) ((w)->devPrivates[PictureWindowPrivateIndex].ptr = (pointer) (p)) + +#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, PictureType, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +Bool +PictureDestroyWindow (WindowPtr pWindow); + +Bool +PictureCloseScreen (int Index, ScreenPtr pScreen); + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef); + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen); + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel); + +int +PictureGetSubpixelOrder (ScreenPtr pScreen); + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp); + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual); + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format); + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +int +PictureGetFilterId (char *filter, int len, Bool makeit); + +char * +PictureGetFilterName (int id); + +int +PictureAddFilter (ScreenPtr pScreen, char *filter, xFixed *params, int nparams); + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias); + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen); + +void +PictureResetFilters (ScreenPtr pScreen); + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len); + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams); + +Bool +PictureFinishInit (void); + +void +SetPictureToDefaults (PicturePtr pPicture); + +PicturePtr +AllocatePicture (ScreenPtr pScreen); + +#if 0 +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); +#endif + + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask mask, + XID *list, + ClientPtr client, + int *error); + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client); + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects); + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform); + +void +ValidatePicture(PicturePtr pPicture); + +int +FreePicture (pointer pPicture, + XID pid); + +int +FreePictFormat (pointer pPictFormat, + XID pid); + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs); + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles); + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector); + +void RenderExtensionInit (void); + +Bool +AnimCurInit (ScreenPtr pScreen); + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor); + +#ifdef PANORAMIX +void PanoramiXRenderInit (void); +void PanoramiXRenderReset (void); +#endif + +#endif /* _PICTURESTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c new file mode 100644 index 000000000..f5cf91607 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c @@ -0,0 +1,921 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXproperty.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/property.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: property.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xproto.h" +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#include "lbxtags.h" +#endif + +#include "Options.h" +#include "Rootless.h" +#include "Client.h" + +#if defined(LBX) || defined(LBX_COMPAT) +int fWriteToClient(client, len, buf) + ClientPtr client; + int len; + char *buf; +{ + return WriteToClient(client, len, buf); +} +#endif + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(client) + ClientPtr client; +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XCSECURITY + char action = SecurityCheckPropertyAccess(client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XCSECURITY + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XCSECURITY + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(client) + ClientPtr client; +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + +#ifdef NXAGENT_CLIPBOARD + { + extern WindowPtr nxagentGetClipboardWindow(Atom, WindowPtr); + + pWin = nxagentGetClipboardWindow(stuff->property, NULL); + } + + if (pWin == NULL) +#endif + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + +#ifdef NXAGENT_ARTSD + { + /* Do not process MCOPGLOBALS property changes, + they are already set reflecting the server side settings. + Just return success. + */ + extern Atom mcop_local_atom; + if (stuff->property == mcop_local_atom) + return client->noClientException; + } +#endif + +#ifdef LBX + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL); +#else + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); +#endif + if (err != Success) + return err; + else + { + if (nxagentOption(Rootless) == 1) + { + nxagentExportProperty(pWin, stuff->property, stuff->type, (int) format, + (int) mode, len, (pointer) &stuff[1]); + } + + nxagentGuessClientHint(client, stuff->property, (char *) &stuff[1]); + + nxagentGuessShadowHint(client, stuff->property); + + return client->noClientException; + } +} + +int +ChangeWindowProperty(pWin, property, type, format, mode, len, value, sendevent) + WindowPtr pWin; + Atom property, type; + int format, mode; + unsigned long len; + pointer value; + Bool sendevent; +{ +#ifdef LBX + return LbxChangeWindowProperty(NULL, pWin, property, type, + format, mode, len, TRUE, value, + sendevent, NULL); +#else + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +#endif +} + +int +DeleteProperty(pWin, propName) + WindowPtr pWin; + Atom propName; +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply(client, propertyType, format, reply) + ClientPtr client; + ATOM propertyType; + int format; + xGetPropertyReply *reply; +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(client) + ClientPtr client; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XCSECURITY + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } +#ifdef LBX + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } +#endif + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; + case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; + default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +#ifdef NXAGENT_CLIPBOARD +/* GetWindowProperty clipboard use only */ +int +GetWindowProperty(pWin, property, longOffset, longLength, delete, + type, actualType, format, nItems, bytesAfter, propData ) + WindowPtr pWin; + Atom property; + long longOffset; + long longLength; + Bool delete; + Atom type; + Atom *actualType; + int *format; + unsigned long *nItems; + unsigned long *bytesAfter; + unsigned char **propData; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + + if (!pWin) + return BadWindow; + + + if (!ValidAtom(property)) + { + return(BadAtom); + } + if ((type != AnyPropertyType) && !ValidAtom(type)) + { + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + + while (pProp) + { + if (pProp->propertyName == property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + + if (!pProp) + return (BadAtom); + + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((type != pProp->type) && + (type != AnyPropertyType)) + ) + { + *bytesAfter = pProp->size; + *format = pProp->format; + *nItems = 0; + *actualType = pProp->type; + return(Success); + } + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + return BadValue; + } + + len = min(n - ind, 4 * longLength); + + *bytesAfter = n - (ind + len); + *format = pProp->format; + *nItems = len / (pProp->format / 8 ); + *actualType = pProp->type; + + if (delete && (*bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + if (len) + { + *propData = (unsigned char *)(pProp->data) + ind; + } + + if (delete && (*bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} +#endif + +int +ProcListProperties(client) + ClientPtr client; +{ + Atom *pAtoms = NULL, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(client) + register ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XCSECURITY + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.NX.original new file mode 100644 index 000000000..f5cf91607 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.NX.original @@ -0,0 +1,921 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXproperty.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/property.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: property.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xproto.h" +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#include "lbxtags.h" +#endif + +#include "Options.h" +#include "Rootless.h" +#include "Client.h" + +#if defined(LBX) || defined(LBX_COMPAT) +int fWriteToClient(client, len, buf) + ClientPtr client; + int len; + char *buf; +{ + return WriteToClient(client, len, buf); +} +#endif + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(client) + ClientPtr client; +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XCSECURITY + char action = SecurityCheckPropertyAccess(client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XCSECURITY + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XCSECURITY + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(client) + ClientPtr client; +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + +#ifdef NXAGENT_CLIPBOARD + { + extern WindowPtr nxagentGetClipboardWindow(Atom, WindowPtr); + + pWin = nxagentGetClipboardWindow(stuff->property, NULL); + } + + if (pWin == NULL) +#endif + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + +#ifdef NXAGENT_ARTSD + { + /* Do not process MCOPGLOBALS property changes, + they are already set reflecting the server side settings. + Just return success. + */ + extern Atom mcop_local_atom; + if (stuff->property == mcop_local_atom) + return client->noClientException; + } +#endif + +#ifdef LBX + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL); +#else + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); +#endif + if (err != Success) + return err; + else + { + if (nxagentOption(Rootless) == 1) + { + nxagentExportProperty(pWin, stuff->property, stuff->type, (int) format, + (int) mode, len, (pointer) &stuff[1]); + } + + nxagentGuessClientHint(client, stuff->property, (char *) &stuff[1]); + + nxagentGuessShadowHint(client, stuff->property); + + return client->noClientException; + } +} + +int +ChangeWindowProperty(pWin, property, type, format, mode, len, value, sendevent) + WindowPtr pWin; + Atom property, type; + int format, mode; + unsigned long len; + pointer value; + Bool sendevent; +{ +#ifdef LBX + return LbxChangeWindowProperty(NULL, pWin, property, type, + format, mode, len, TRUE, value, + sendevent, NULL); +#else + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +#endif +} + +int +DeleteProperty(pWin, propName) + WindowPtr pWin; + Atom propName; +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply(client, propertyType, format, reply) + ClientPtr client; + ATOM propertyType; + int format; + xGetPropertyReply *reply; +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(client) + ClientPtr client; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XCSECURITY + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } +#ifdef LBX + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } +#endif + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; + case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; + default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +#ifdef NXAGENT_CLIPBOARD +/* GetWindowProperty clipboard use only */ +int +GetWindowProperty(pWin, property, longOffset, longLength, delete, + type, actualType, format, nItems, bytesAfter, propData ) + WindowPtr pWin; + Atom property; + long longOffset; + long longLength; + Bool delete; + Atom type; + Atom *actualType; + int *format; + unsigned long *nItems; + unsigned long *bytesAfter; + unsigned char **propData; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + + if (!pWin) + return BadWindow; + + + if (!ValidAtom(property)) + { + return(BadAtom); + } + if ((type != AnyPropertyType) && !ValidAtom(type)) + { + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + + while (pProp) + { + if (pProp->propertyName == property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + + if (!pProp) + return (BadAtom); + + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((type != pProp->type) && + (type != AnyPropertyType)) + ) + { + *bytesAfter = pProp->size; + *format = pProp->format; + *nItems = 0; + *actualType = pProp->type; + return(Success); + } + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + return BadValue; + } + + len = min(n - ind, 4 * longLength); + + *bytesAfter = n - (ind + len); + *format = pProp->format; + *nItems = len / (pProp->format / 8 ); + *actualType = pProp->type; + + if (delete && (*bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + if (len) + { + *propData = (unsigned char *)(pProp->data) + ind; + } + + if (delete && (*bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} +#endif + +int +ProcListProperties(client) + ClientPtr client; +{ + Atom *pAtoms = NULL, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(client) + register ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XCSECURITY + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.XF86.original new file mode 100644 index 000000000..ba12faffe --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.XF86.original @@ -0,0 +1,736 @@ +/* $XFree86: xc/programs/Xserver/dix/property.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: property.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#include "X.h" +#define NEED_REPLIES +#define NEED_EVENTS +#include "Xproto.h" +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "dispatch.h" +#include "swaprep.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif +#ifdef LBX +#include "lbxserve.h" +#include "lbxtags.h" +#endif + +#if defined(LBX) || defined(LBX_COMPAT) +int fWriteToClient(ClientPtr client, int len, char *buf) +{ + return WriteToClient(client, len, buf); +} +#endif + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(client) + ClientPtr client; +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XCSECURITY + char action = SecurityCheckPropertyAccess(client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XCSECURITY + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XCSECURITY + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(client) + ClientPtr client; +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + +#ifdef LBX + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL); +#else + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); +#endif + if (err != Success) + return err; + else + return client->noClientException; +} + +int +ChangeWindowProperty(pWin, property, type, format, mode, len, value, sendevent) + WindowPtr pWin; + Atom property, type; + int format, mode; + unsigned long len; + pointer value; + Bool sendevent; +{ +#ifdef LBX + return LbxChangeWindowProperty(NULL, pWin, property, type, + format, mode, len, TRUE, value, + sendevent, NULL); +#else + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +#endif +} + +int +DeleteProperty(pWin, propName) + WindowPtr pWin; + Atom propName; +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply(client, propertyType, format, reply) + ClientPtr client; + ATOM propertyType; + int format; + xGetPropertyReply *reply; +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(client) + ClientPtr client; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XCSECURITY + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } +#ifdef LBX + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } +#endif + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; + case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; + default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +int +ProcListProperties(client) + ClientPtr client; +{ + Atom *pAtoms = NULL, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(client) + register ClientPtr client; +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XCSECURITY + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c b/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c new file mode 100644 index 000000000..6f53dcdad --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c @@ -0,0 +1,1229 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXrandr.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.19 2003/02/08 03:52:30 dawes Exp $ + * + * Copyright © 2000, Compaq Computer Corporation, + * Copyright © 2002, Hewlett Packard, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + */ + + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include "randr.h" +#include "randrproto.h" +#include "../../randr/randrstr.h" +#include "render.h" /* we share subpixel order information */ +#include "picturestr.h" +#include "Xfuncproto.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#define RR_VALIDATE +int RRGeneration; +int RRNScreens; + +static int ProcRRQueryVersion (ClientPtr pClient); +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); +static int SProcRRQueryVersion (ClientPtr pClient); + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static CARD8 RRReqCode; +static int RRErrBase; +static int RREventBase; +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static int RRClientPrivateIndex; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +int rrPrivIndex = -1; + +#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +static Bool +RRClientKnowsRates (ClientPtr pClient) +{ + rrClientPriv(pClient); + + return (pRRClient->major_version > 1 || + (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); +} + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static void +RRResetProc (ExtensionEntry *extEntry) +{ +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CloseScreen); + if (pScrPriv->pSizes) + xfree (pScrPriv->pSizes); + xfree (pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); + cpswaps(from->subpixelOrder, to->subpixelOrder); +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (RRGeneration != serverGeneration) + { + if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + RRGeneration = serverGeneration; + } + + pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrSetConfig = 0; + pScrPriv->rrGetInfo = 0; + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScrPriv->rotations = RR_Rotate_0; + + pScrPriv->nSizes = 0; + pScrPriv->nSizesInUse = 0; + pScrPriv->pSizes = 0; + + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->size = -1; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + xfree ((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + RRClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RRClientPrivateIndex, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + ClientType = CreateNewResourceType(RRFreeClient); + if (!ClientType) + return; + EventType = CreateNewResourceType(RRFreeEvents); + if (!EventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + RRResetProc, StandardMinorOpcode); + if (!extEntry) + return; + RRReqCode = (CARD8) extEntry->base; + RRErrBase = extEntry->errorBase; + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + + return; +} + +int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + xRRScreenChangeNotifyEvent se; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + RRScreenSizePtr pSize; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + + pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType); + if (!pHead) + return WT_WALKCHILDREN; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) pScrPriv->rotation; + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); + if (pScrPriv->size >= 0) + { + pSize = &pScrPriv->pSizes[pScrPriv->size]; + se.sizeID = pSize->id; + se.widthInPixels = pSize->width; + se.heightInPixels = pSize->height; + se.widthInMillimeters = pSize->mmWidth; + se.heightInMillimeters = pSize->mmHeight; + } + else + { + /* + * This "shouldn't happen", but a broken DDX can + * forget to set the current configuration on GetInfo + */ + se.sizeID = 0xffff; + se.widthInPixels = 0; + se.heightInPixels = 0; + se.widthInMillimeters = 0; + se.heightInMillimeters = 0; + } + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + se.sequenceNumber = client->sequence; + if(pRREvent->mask & RRScreenChangeNotifyMask) + WriteEventsToClient (client, 1, (xEvent *) &se); + } + return WT_WALKCHILDREN; +} + +Bool +RRGetInfo (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i, j, k, l; + Bool changed; + Rotation rotations; + RRScreenSizePtr pSize; + RRScreenRatePtr pRate; + + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + pSize->oldReferenced = pSize->referenced; + pSize->referenced = FALSE; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + pRate->oldReferenced = pRate->referenced; + pRate->referenced = FALSE; + } + } + if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) + return FALSE; + + changed = FALSE; + + /* + * Check whether anything changed and simultaneously generate + * the protocol id values for the objects + */ + if (rotations != pScrPriv->rotations) + { + pScrPriv->rotations = rotations; + changed = TRUE; + } + + j = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->oldReferenced != pSize->referenced) + changed = TRUE; + if (pSize->referenced) + pSize->id = j++; + l = 0; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + if (pRate->oldReferenced != pRate->referenced) + changed = TRUE; + if (pRate->referenced) + l++; + } + pSize->nRatesInUse = l; + } + pScrPriv->nSizesInUse = j; + if (changed) + { + UpdateCurrentTime (); + pScrPriv->lastConfigTime = currentTime; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + } + return TRUE; +} + +void +RRSendConfigNotify (ScreenPtr pScreen) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + xEvent event; + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = 0; + event.u.configureNotify.y = 0; + + /* XXX xinerama stuff ? */ + + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep; + register int n; + REQUEST(xRRQueryVersionReq); + rrClientPriv(client); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + pRRClient->major_version = stuff->majorVersion; + pRRClient->minor_version = stuff->minorVersion; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RANDR_MAJOR; + rep.minorVersion = RANDR_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +extern char *ConnectionInfo; + +static int padlength[4] = {0, 3, 2, 1}; + +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 int +ProcRRGetScreenInfo (ClientPtr client) +{ + REQUEST(xRRGetScreenInfoReq); + xRRGetScreenInfoReply rep; + WindowPtr pWin; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + int extraLen; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + + if (!pWin) + return BadWindow; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + if (!pScrPriv) + { + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0;; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nSizes = 0; + rep.sizeID = 0; + rep.rotation = RR_Rotate_0; + rep.rate = 0; + rep.nrateEnts = 0; + extra = 0; + extraLen = 0; + } + else + { + int i, j; + xScreenSizes *size; + CARD16 *rates; + CARD8 *data8; + Bool has_rate = RRClientKnowsRates (client); + + RRGetInfo (pScreen); + + rep.type = X_Reply; + rep.setOfRotations = pScrPriv->rotations; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.rotation = pScrPriv->rotation; + rep.nSizes = pScrPriv->nSizesInUse; + rep.rate = pScrPriv->rate; + rep.nrateEnts = 0; + if (has_rate) + { + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + rep.nrateEnts += (1 + pSize->nRatesInUse); + } + } + } + + if (pScrPriv->size >= 0) + rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id; + else + return BadImplementation; + + extraLen = (rep.nSizes * sizeof (xScreenSizes) + + rep.nrateEnts * sizeof (CARD16)); + + extra = (CARD8 *) xalloc (extraLen); + if (!extra) + return BadAlloc; + /* + * First comes the size information + */ + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + size->widthInPixels = pSize->width; + size->heightInPixels = pSize->height; + size->widthInMillimeters = pSize->mmWidth; + size->heightInMillimeters = pSize->mmHeight; + if (client->swapped) + { + swaps (&size->widthInPixels, n); + swaps (&size->heightInPixels, n); + swaps (&size->widthInMillimeters, n); + swaps (&size->heightInMillimeters, n); + } + size++; + if (has_rate) + { + *rates = pSize->nRatesInUse; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + for (j = 0; j < pSize->nRates; j++) + { + RRScreenRatePtr pRate = &pSize->pRates[j]; + if (pRate->referenced) + { + *rates = pRate->rate; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + } + } + } + } + } + data8 = (CARD8 *) rates; + + if (data8 - (CARD8 *) extra != extraLen) + FatalError ("RRGetScreenInfo bad extra len %d != %d\n", + data8 - (CARD8 *) extra, extraLen); + rep.length = (extraLen + 3) >> 2; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.rotation, n); + swaps(&rep.nSizes, n); + swaps(&rep.sizeID, n); + swaps(&rep.rate, n); + swaps(&rep.nrateEnts, n); + } + WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + xfree (extra); + } + return (client->noClientException); +} + +static int +ProcRRSetScreenConfig (ClientPtr client) +{ + REQUEST(xRRSetScreenConfigReq); + xRRSetScreenConfigReply rep; + DrawablePtr pDraw; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp configTime; + TimeStamp time; + RRScreenSizePtr pSize; + int i; + Rotation rotation; + int rate; + short oldWidth, oldHeight; + Bool has_rate; + + UpdateCurrentTime (); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + has_rate = TRUE; + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + has_rate = FALSE; + } + + SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client, + SecurityWriteAccess); + + pScreen = pDraw->pScreen; + + pScrPriv= rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * if the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated + */ + if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } + + /* + * Search for the requested size + */ + pSize = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced && pSize->id == stuff->sizeID) + { + break; + } + } + if (i == pScrPriv->nSizes) + { + /* + * Invalid size ID + */ + client->errorValue = stuff->sizeID; + return BadValue; + } + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (has_rate) + rate = (int) stuff->rate; + else + rate = 0; + + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + client->errorValue = rate; + return BadValue; + } + } + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + rep.status = RRSetConfigFailed; + goto sendReply; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + pScrPriv->lastSetTime = time; + + /* + * Report Success + */ + rep.status = RRSetConfigSuccess; + +sendReply: + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + swapl(&rep.newConfigTimestamp, n); + swapl(&rep.root, n); + } + WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); + + return (client->noClientException); +} + +static int +ProcRRSelectInput (ClientPtr client) +{ + REQUEST(xRRSelectInputReq); + rrClientPriv(client); + RRTimesPtr pTimes; + WindowPtr pWin; + RREventPtr pRREvent, pNewRREvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH(xRRSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (RREventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, + SecurityWriteAccess); + + if (stuff->enable & (RRScreenChangeNotifyMask)) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + + if (pHead) + { + /* check for existing entry. */ + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + if (pRREvent->client == client) + return Success; + } + + /* build the entry */ + pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec)); + if (!pNewRREvent) + return BadAlloc; + pNewRREvent->next = 0; + pNewRREvent->client = client; + pNewRREvent->window = pWin; + pNewRREvent->mask = stuff->enable; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewRREvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent)) + 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 = (RREventPtr *) xalloc (sizeof (RREventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewRREvent->next = *pHead; + *pHead = pNewRREvent; + /* + * Now see if the client needs an event + */ + if (pScrPriv) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + TellChanged (pWin, (pointer) pScreen); + } + } + } + else if (stuff->enable == xFalse) + { + /* delete the interest */ + if (pHead) { + pNewRREvent = 0; + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (pRREvent->client == client) + break; + pNewRREvent = pRREvent; + } + if (pRREvent) { + FreeResource (pRREvent->clientResource, ClientType); + if (pNewRREvent) + pNewRREvent->next = pRREvent->next; + else + *pHead = pRREvent->next; + xfree (pRREvent); + } + } + } + else + { + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return ProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return ProcRRSetScreenConfig(client); + case X_RRSelectInput: + return ProcRRSelectInput(client); + case X_RRGetScreenInfo: + return ProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + +static int +SProcRRQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRRQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return ProcRRQueryVersion(client); +} + +static int +SProcRRGetScreenInfo (ClientPtr client) +{ + register int n; + REQUEST(xRRGetScreenInfoReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRGetScreenInfo(client); +} + +static int +SProcRRSetScreenConfig (ClientPtr client) +{ + register int n; + REQUEST(xRRSetScreenConfigReq); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + swaps (&stuff->rate, n); + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + } + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->sizeID, n); + swaps(&stuff->rotation, n); + return ProcRRSetScreenConfig(client); +} + +static int +SProcRRSelectInput (ClientPtr client) +{ + register int n; + REQUEST(xRRSelectInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRSelectInput(client); +} + + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return SProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return SProcRRSetScreenConfig(client); + case X_RRSelectInput: + return SProcRRSelectInput(client); + case X_RRGetScreenInfo: + return SProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + + +static Bool +RRScreenSizeMatches (RRScreenSizePtr a, + RRScreenSizePtr b) +{ + if (a->width != b->width) + return FALSE; + if (a->height != b->height) + return FALSE; + if (a->mmWidth != b->mmWidth) + return FALSE; + if (a->mmHeight != b->mmHeight) + return FALSE; + return TRUE; +} + +RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight) +{ + rrScrPriv (pScreen); + int i; + RRScreenSize tmp; + RRScreenSizePtr pNew; + + if (!pScrPriv) + return 0; + + /* + * FIXME: The compiler reports that field + * id is used uninitialized here. + */ + + tmp.id = 0; + + tmp.width = width; + tmp.height= height; + tmp.mmWidth = mmWidth; + tmp.mmHeight = mmHeight; + tmp.pRates = 0; + tmp.nRates = 0; + tmp.nRatesInUse = 0; + tmp.referenced = TRUE; + tmp.oldReferenced = FALSE; + for (i = 0; i < pScrPriv->nSizes; i++) + if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i])) + { + pScrPriv->pSizes[i].referenced = TRUE; + return &pScrPriv->pSizes[i]; + } + pNew = xrealloc (pScrPriv->pSizes, + (pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); + if (!pNew) + return 0; + pNew[pScrPriv->nSizes++] = tmp; + pScrPriv->pSizes = pNew; + return &pNew[pScrPriv->nSizes-1]; +} + +Bool RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate) +{ + rrScrPriv(pScreen); + int i; + RRScreenRatePtr pNew, pRate; + + if (!pScrPriv) + return FALSE; + + for (i = 0; i < pSize->nRates; i++) + { + pRate = &pSize->pRates[i]; + if (pRate->rate == rate) + { + pRate->referenced = TRUE; + return TRUE; + } + } + + pNew = xrealloc (pSize->pRates, + (pSize->nRates + 1) * sizeof (RRScreenRate)); + if (!pNew) + return FALSE; + pRate = &pNew[pSize->nRates++]; + pRate->rate = rate; + pRate->referenced = TRUE; + pRate->oldReferenced = FALSE; + pSize->pRates = pNew; + return TRUE; +} + +void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + + pScrPriv->rotation = rotation; + pScrPriv->size = pSize - pScrPriv->pSizes; + pScrPriv->rate = rate; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.NX.original new file mode 100644 index 000000000..6f53dcdad --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.NX.original @@ -0,0 +1,1229 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXrandr.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.19 2003/02/08 03:52:30 dawes Exp $ + * + * Copyright © 2000, Compaq Computer Corporation, + * Copyright © 2002, Hewlett Packard, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + */ + + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include "randr.h" +#include "randrproto.h" +#include "../../randr/randrstr.h" +#include "render.h" /* we share subpixel order information */ +#include "picturestr.h" +#include "Xfuncproto.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#define RR_VALIDATE +int RRGeneration; +int RRNScreens; + +static int ProcRRQueryVersion (ClientPtr pClient); +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); +static int SProcRRQueryVersion (ClientPtr pClient); + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static CARD8 RRReqCode; +static int RRErrBase; +static int RREventBase; +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static int RRClientPrivateIndex; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +int rrPrivIndex = -1; + +#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +static Bool +RRClientKnowsRates (ClientPtr pClient) +{ + rrClientPriv(pClient); + + return (pRRClient->major_version > 1 || + (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); +} + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static void +RRResetProc (ExtensionEntry *extEntry) +{ +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CloseScreen); + if (pScrPriv->pSizes) + xfree (pScrPriv->pSizes); + xfree (pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); + cpswaps(from->subpixelOrder, to->subpixelOrder); +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (RRGeneration != serverGeneration) + { + if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + RRGeneration = serverGeneration; + } + + pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrSetConfig = 0; + pScrPriv->rrGetInfo = 0; + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScrPriv->rotations = RR_Rotate_0; + + pScrPriv->nSizes = 0; + pScrPriv->nSizesInUse = 0; + pScrPriv->pSizes = 0; + + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->size = -1; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + xfree ((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + RRClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RRClientPrivateIndex, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + ClientType = CreateNewResourceType(RRFreeClient); + if (!ClientType) + return; + EventType = CreateNewResourceType(RRFreeEvents); + if (!EventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + RRResetProc, StandardMinorOpcode); + if (!extEntry) + return; + RRReqCode = (CARD8) extEntry->base; + RRErrBase = extEntry->errorBase; + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + + return; +} + +int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + xRRScreenChangeNotifyEvent se; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + RRScreenSizePtr pSize; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + + pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType); + if (!pHead) + return WT_WALKCHILDREN; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) pScrPriv->rotation; + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); + if (pScrPriv->size >= 0) + { + pSize = &pScrPriv->pSizes[pScrPriv->size]; + se.sizeID = pSize->id; + se.widthInPixels = pSize->width; + se.heightInPixels = pSize->height; + se.widthInMillimeters = pSize->mmWidth; + se.heightInMillimeters = pSize->mmHeight; + } + else + { + /* + * This "shouldn't happen", but a broken DDX can + * forget to set the current configuration on GetInfo + */ + se.sizeID = 0xffff; + se.widthInPixels = 0; + se.heightInPixels = 0; + se.widthInMillimeters = 0; + se.heightInMillimeters = 0; + } + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + se.sequenceNumber = client->sequence; + if(pRREvent->mask & RRScreenChangeNotifyMask) + WriteEventsToClient (client, 1, (xEvent *) &se); + } + return WT_WALKCHILDREN; +} + +Bool +RRGetInfo (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i, j, k, l; + Bool changed; + Rotation rotations; + RRScreenSizePtr pSize; + RRScreenRatePtr pRate; + + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + pSize->oldReferenced = pSize->referenced; + pSize->referenced = FALSE; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + pRate->oldReferenced = pRate->referenced; + pRate->referenced = FALSE; + } + } + if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) + return FALSE; + + changed = FALSE; + + /* + * Check whether anything changed and simultaneously generate + * the protocol id values for the objects + */ + if (rotations != pScrPriv->rotations) + { + pScrPriv->rotations = rotations; + changed = TRUE; + } + + j = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->oldReferenced != pSize->referenced) + changed = TRUE; + if (pSize->referenced) + pSize->id = j++; + l = 0; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + if (pRate->oldReferenced != pRate->referenced) + changed = TRUE; + if (pRate->referenced) + l++; + } + pSize->nRatesInUse = l; + } + pScrPriv->nSizesInUse = j; + if (changed) + { + UpdateCurrentTime (); + pScrPriv->lastConfigTime = currentTime; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + } + return TRUE; +} + +void +RRSendConfigNotify (ScreenPtr pScreen) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + xEvent event; + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = 0; + event.u.configureNotify.y = 0; + + /* XXX xinerama stuff ? */ + + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep; + register int n; + REQUEST(xRRQueryVersionReq); + rrClientPriv(client); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + pRRClient->major_version = stuff->majorVersion; + pRRClient->minor_version = stuff->minorVersion; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RANDR_MAJOR; + rep.minorVersion = RANDR_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +extern char *ConnectionInfo; + +static int padlength[4] = {0, 3, 2, 1}; + +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 int +ProcRRGetScreenInfo (ClientPtr client) +{ + REQUEST(xRRGetScreenInfoReq); + xRRGetScreenInfoReply rep; + WindowPtr pWin; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + int extraLen; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + + if (!pWin) + return BadWindow; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + if (!pScrPriv) + { + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0;; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nSizes = 0; + rep.sizeID = 0; + rep.rotation = RR_Rotate_0; + rep.rate = 0; + rep.nrateEnts = 0; + extra = 0; + extraLen = 0; + } + else + { + int i, j; + xScreenSizes *size; + CARD16 *rates; + CARD8 *data8; + Bool has_rate = RRClientKnowsRates (client); + + RRGetInfo (pScreen); + + rep.type = X_Reply; + rep.setOfRotations = pScrPriv->rotations; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.rotation = pScrPriv->rotation; + rep.nSizes = pScrPriv->nSizesInUse; + rep.rate = pScrPriv->rate; + rep.nrateEnts = 0; + if (has_rate) + { + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + rep.nrateEnts += (1 + pSize->nRatesInUse); + } + } + } + + if (pScrPriv->size >= 0) + rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id; + else + return BadImplementation; + + extraLen = (rep.nSizes * sizeof (xScreenSizes) + + rep.nrateEnts * sizeof (CARD16)); + + extra = (CARD8 *) xalloc (extraLen); + if (!extra) + return BadAlloc; + /* + * First comes the size information + */ + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + size->widthInPixels = pSize->width; + size->heightInPixels = pSize->height; + size->widthInMillimeters = pSize->mmWidth; + size->heightInMillimeters = pSize->mmHeight; + if (client->swapped) + { + swaps (&size->widthInPixels, n); + swaps (&size->heightInPixels, n); + swaps (&size->widthInMillimeters, n); + swaps (&size->heightInMillimeters, n); + } + size++; + if (has_rate) + { + *rates = pSize->nRatesInUse; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + for (j = 0; j < pSize->nRates; j++) + { + RRScreenRatePtr pRate = &pSize->pRates[j]; + if (pRate->referenced) + { + *rates = pRate->rate; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + } + } + } + } + } + data8 = (CARD8 *) rates; + + if (data8 - (CARD8 *) extra != extraLen) + FatalError ("RRGetScreenInfo bad extra len %d != %d\n", + data8 - (CARD8 *) extra, extraLen); + rep.length = (extraLen + 3) >> 2; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.rotation, n); + swaps(&rep.nSizes, n); + swaps(&rep.sizeID, n); + swaps(&rep.rate, n); + swaps(&rep.nrateEnts, n); + } + WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + xfree (extra); + } + return (client->noClientException); +} + +static int +ProcRRSetScreenConfig (ClientPtr client) +{ + REQUEST(xRRSetScreenConfigReq); + xRRSetScreenConfigReply rep; + DrawablePtr pDraw; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp configTime; + TimeStamp time; + RRScreenSizePtr pSize; + int i; + Rotation rotation; + int rate; + short oldWidth, oldHeight; + Bool has_rate; + + UpdateCurrentTime (); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + has_rate = TRUE; + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + has_rate = FALSE; + } + + SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client, + SecurityWriteAccess); + + pScreen = pDraw->pScreen; + + pScrPriv= rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * if the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated + */ + if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } + + /* + * Search for the requested size + */ + pSize = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced && pSize->id == stuff->sizeID) + { + break; + } + } + if (i == pScrPriv->nSizes) + { + /* + * Invalid size ID + */ + client->errorValue = stuff->sizeID; + return BadValue; + } + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (has_rate) + rate = (int) stuff->rate; + else + rate = 0; + + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + client->errorValue = rate; + return BadValue; + } + } + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + rep.status = RRSetConfigFailed; + goto sendReply; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + pScrPriv->lastSetTime = time; + + /* + * Report Success + */ + rep.status = RRSetConfigSuccess; + +sendReply: + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + swapl(&rep.newConfigTimestamp, n); + swapl(&rep.root, n); + } + WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); + + return (client->noClientException); +} + +static int +ProcRRSelectInput (ClientPtr client) +{ + REQUEST(xRRSelectInputReq); + rrClientPriv(client); + RRTimesPtr pTimes; + WindowPtr pWin; + RREventPtr pRREvent, pNewRREvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH(xRRSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (RREventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, + SecurityWriteAccess); + + if (stuff->enable & (RRScreenChangeNotifyMask)) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + + if (pHead) + { + /* check for existing entry. */ + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + if (pRREvent->client == client) + return Success; + } + + /* build the entry */ + pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec)); + if (!pNewRREvent) + return BadAlloc; + pNewRREvent->next = 0; + pNewRREvent->client = client; + pNewRREvent->window = pWin; + pNewRREvent->mask = stuff->enable; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewRREvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent)) + 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 = (RREventPtr *) xalloc (sizeof (RREventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewRREvent->next = *pHead; + *pHead = pNewRREvent; + /* + * Now see if the client needs an event + */ + if (pScrPriv) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + TellChanged (pWin, (pointer) pScreen); + } + } + } + else if (stuff->enable == xFalse) + { + /* delete the interest */ + if (pHead) { + pNewRREvent = 0; + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (pRREvent->client == client) + break; + pNewRREvent = pRREvent; + } + if (pRREvent) { + FreeResource (pRREvent->clientResource, ClientType); + if (pNewRREvent) + pNewRREvent->next = pRREvent->next; + else + *pHead = pRREvent->next; + xfree (pRREvent); + } + } + } + else + { + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return ProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return ProcRRSetScreenConfig(client); + case X_RRSelectInput: + return ProcRRSelectInput(client); + case X_RRGetScreenInfo: + return ProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + +static int +SProcRRQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRRQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return ProcRRQueryVersion(client); +} + +static int +SProcRRGetScreenInfo (ClientPtr client) +{ + register int n; + REQUEST(xRRGetScreenInfoReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRGetScreenInfo(client); +} + +static int +SProcRRSetScreenConfig (ClientPtr client) +{ + register int n; + REQUEST(xRRSetScreenConfigReq); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + swaps (&stuff->rate, n); + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + } + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->sizeID, n); + swaps(&stuff->rotation, n); + return ProcRRSetScreenConfig(client); +} + +static int +SProcRRSelectInput (ClientPtr client) +{ + register int n; + REQUEST(xRRSelectInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRSelectInput(client); +} + + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return SProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return SProcRRSetScreenConfig(client); + case X_RRSelectInput: + return SProcRRSelectInput(client); + case X_RRGetScreenInfo: + return SProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + + +static Bool +RRScreenSizeMatches (RRScreenSizePtr a, + RRScreenSizePtr b) +{ + if (a->width != b->width) + return FALSE; + if (a->height != b->height) + return FALSE; + if (a->mmWidth != b->mmWidth) + return FALSE; + if (a->mmHeight != b->mmHeight) + return FALSE; + return TRUE; +} + +RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight) +{ + rrScrPriv (pScreen); + int i; + RRScreenSize tmp; + RRScreenSizePtr pNew; + + if (!pScrPriv) + return 0; + + /* + * FIXME: The compiler reports that field + * id is used uninitialized here. + */ + + tmp.id = 0; + + tmp.width = width; + tmp.height= height; + tmp.mmWidth = mmWidth; + tmp.mmHeight = mmHeight; + tmp.pRates = 0; + tmp.nRates = 0; + tmp.nRatesInUse = 0; + tmp.referenced = TRUE; + tmp.oldReferenced = FALSE; + for (i = 0; i < pScrPriv->nSizes; i++) + if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i])) + { + pScrPriv->pSizes[i].referenced = TRUE; + return &pScrPriv->pSizes[i]; + } + pNew = xrealloc (pScrPriv->pSizes, + (pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); + if (!pNew) + return 0; + pNew[pScrPriv->nSizes++] = tmp; + pScrPriv->pSizes = pNew; + return &pNew[pScrPriv->nSizes-1]; +} + +Bool RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate) +{ + rrScrPriv(pScreen); + int i; + RRScreenRatePtr pNew, pRate; + + if (!pScrPriv) + return FALSE; + + for (i = 0; i < pSize->nRates; i++) + { + pRate = &pSize->pRates[i]; + if (pRate->rate == rate) + { + pRate->referenced = TRUE; + return TRUE; + } + } + + pNew = xrealloc (pSize->pRates, + (pSize->nRates + 1) * sizeof (RRScreenRate)); + if (!pNew) + return FALSE; + pRate = &pNew[pSize->nRates++]; + pRate->rate = rate; + pRate->referenced = TRUE; + pRate->oldReferenced = FALSE; + pSize->pRates = pNew; + return TRUE; +} + +void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + + pScrPriv->rotation = rotation; + pScrPriv->size = pSize - pScrPriv->pSizes; + pScrPriv->rate = rate; +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.XF86.original new file mode 100644 index 000000000..666605e96 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXrandr.c.XF86.original @@ -0,0 +1,1197 @@ +/* + * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.19 2003/02/08 03:52:30 dawes Exp $ + * + * Copyright © 2000, Compaq Computer Corporation, + * Copyright © 2002, Hewlett Packard, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + */ + + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include "randr.h" +#include "randrproto.h" +#include "randrstr.h" +#include "render.h" /* we share subpixel order information */ +#include "picturestr.h" +#include "Xfuncproto.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#define RR_VALIDATE +int RRGeneration; +int RRNScreens; + +static int ProcRRQueryVersion (ClientPtr pClient); +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); +static int SProcRRQueryVersion (ClientPtr pClient); + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static CARD8 RRReqCode; +static int RRErrBase; +static int RREventBase; +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static int RRClientPrivateIndex; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +int rrPrivIndex = -1; + +#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +static Bool +RRClientKnowsRates (ClientPtr pClient) +{ + rrClientPriv(pClient); + + return (pRRClient->major_version > 1 || + (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); +} + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static void +RRResetProc (ExtensionEntry *extEntry) +{ +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CloseScreen); + if (pScrPriv->pSizes) + xfree (pScrPriv->pSizes); + xfree (pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); + cpswaps(from->subpixelOrder, to->subpixelOrder); +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (RRGeneration != serverGeneration) + { + if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + RRGeneration = serverGeneration; + } + + pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrSetConfig = 0; + pScrPriv->rrGetInfo = 0; + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScrPriv->rotations = RR_Rotate_0; + + pScrPriv->nSizes = 0; + pScrPriv->nSizesInUse = 0; + pScrPriv->pSizes = 0; + + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->size = -1; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + xfree ((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + RRClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RRClientPrivateIndex, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + ClientType = CreateNewResourceType(RRFreeClient); + if (!ClientType) + return; + EventType = CreateNewResourceType(RRFreeEvents); + if (!EventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + RRResetProc, StandardMinorOpcode); + if (!extEntry) + return; + RRReqCode = (CARD8) extEntry->base; + RRErrBase = extEntry->errorBase; + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + + return; +} + +static int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + xRRScreenChangeNotifyEvent se; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + RRScreenSizePtr pSize; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + + pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType); + if (!pHead) + return WT_WALKCHILDREN; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) pScrPriv->rotation; + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); + if (pScrPriv->size >= 0) + { + pSize = &pScrPriv->pSizes[pScrPriv->size]; + se.sizeID = pSize->id; + se.widthInPixels = pSize->width; + se.heightInPixels = pSize->height; + se.widthInMillimeters = pSize->mmWidth; + se.heightInMillimeters = pSize->mmHeight; + } + else + { + /* + * This "shouldn't happen", but a broken DDX can + * forget to set the current configuration on GetInfo + */ + se.sizeID = 0xffff; + se.widthInPixels = 0; + se.heightInPixels = 0; + se.widthInMillimeters = 0; + se.heightInMillimeters = 0; + } + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + se.sequenceNumber = client->sequence; + if(pRREvent->mask & RRScreenChangeNotifyMask) + WriteEventsToClient (client, 1, (xEvent *) &se); + } + return WT_WALKCHILDREN; +} + +static Bool +RRGetInfo (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i, j, k, l; + Bool changed; + Rotation rotations; + RRScreenSizePtr pSize; + RRScreenRatePtr pRate; + + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + pSize->oldReferenced = pSize->referenced; + pSize->referenced = FALSE; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + pRate->oldReferenced = pRate->referenced; + pRate->referenced = FALSE; + } + } + if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) + return FALSE; + + changed = FALSE; + + /* + * Check whether anything changed and simultaneously generate + * the protocol id values for the objects + */ + if (rotations != pScrPriv->rotations) + { + pScrPriv->rotations = rotations; + changed = TRUE; + } + + j = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->oldReferenced != pSize->referenced) + changed = TRUE; + if (pSize->referenced) + pSize->id = j++; + l = 0; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + if (pRate->oldReferenced != pRate->referenced) + changed = TRUE; + if (pRate->referenced) + l++; + } + pSize->nRatesInUse = l; + } + pScrPriv->nSizesInUse = j; + if (changed) + { + UpdateCurrentTime (); + pScrPriv->lastConfigTime = currentTime; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + } + return TRUE; +} + +static void +RRSendConfigNotify (ScreenPtr pScreen) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + xEvent event; + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = 0; + event.u.configureNotify.y = 0; + + /* XXX xinerama stuff ? */ + + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep; + register int n; + REQUEST(xRRQueryVersionReq); + rrClientPriv(client); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + pRRClient->major_version = stuff->majorVersion; + pRRClient->minor_version = stuff->minorVersion; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RANDR_MAJOR; + rep.minorVersion = RANDR_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +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 int +ProcRRGetScreenInfo (ClientPtr client) +{ + REQUEST(xRRGetScreenInfoReq); + xRRGetScreenInfoReply rep; + WindowPtr pWin; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + int extraLen; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + + if (!pWin) + return BadWindow; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + if (!pScrPriv) + { + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0;; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nSizes = 0; + rep.sizeID = 0; + rep.rotation = RR_Rotate_0; + rep.rate = 0; + rep.nrateEnts = 0; + extra = 0; + extraLen = 0; + } + else + { + int i, j; + xScreenSizes *size; + CARD16 *rates; + CARD8 *data8; + Bool has_rate = RRClientKnowsRates (client); + + RRGetInfo (pScreen); + + rep.type = X_Reply; + rep.setOfRotations = pScrPriv->rotations; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.rotation = pScrPriv->rotation; + rep.nSizes = pScrPriv->nSizesInUse; + rep.rate = pScrPriv->rate; + rep.nrateEnts = 0; + if (has_rate) + { + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + rep.nrateEnts += (1 + pSize->nRatesInUse); + } + } + } + + if (pScrPriv->size >= 0) + rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id; + else + return BadImplementation; + + extraLen = (rep.nSizes * sizeof (xScreenSizes) + + rep.nrateEnts * sizeof (CARD16)); + + extra = (CARD8 *) xalloc (extraLen); + if (!extra) + return BadAlloc; + /* + * First comes the size information + */ + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + size->widthInPixels = pSize->width; + size->heightInPixels = pSize->height; + size->widthInMillimeters = pSize->mmWidth; + size->heightInMillimeters = pSize->mmHeight; + if (client->swapped) + { + swaps (&size->widthInPixels, n); + swaps (&size->heightInPixels, n); + swaps (&size->widthInMillimeters, n); + swaps (&size->heightInMillimeters, n); + } + size++; + if (has_rate) + { + *rates = pSize->nRatesInUse; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + for (j = 0; j < pSize->nRates; j++) + { + RRScreenRatePtr pRate = &pSize->pRates[j]; + if (pRate->referenced) + { + *rates = pRate->rate; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + } + } + } + } + } + data8 = (CARD8 *) rates; + + if (data8 - (CARD8 *) extra != extraLen) + FatalError ("RRGetScreenInfo bad extra len %d != %d\n", + data8 - (CARD8 *) extra, extraLen); + rep.length = (extraLen + 3) >> 2; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.rotation, n); + swaps(&rep.nSizes, n); + swaps(&rep.sizeID, n); + swaps(&rep.rate, n); + swaps(&rep.nrateEnts, n); + } + WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + xfree (extra); + } + return (client->noClientException); +} + +static int +ProcRRSetScreenConfig (ClientPtr client) +{ + REQUEST(xRRSetScreenConfigReq); + xRRSetScreenConfigReply rep; + DrawablePtr pDraw; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp configTime; + TimeStamp time; + RRScreenSizePtr pSize; + int i; + Rotation rotation; + int rate; + short oldWidth, oldHeight; + Bool has_rate; + + UpdateCurrentTime (); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + has_rate = TRUE; + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + has_rate = FALSE; + } + + SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client, + SecurityWriteAccess); + + pScreen = pDraw->pScreen; + + pScrPriv= rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * if the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated + */ + if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } + + /* + * Search for the requested size + */ + pSize = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced && pSize->id == stuff->sizeID) + { + break; + } + } + if (i == pScrPriv->nSizes) + { + /* + * Invalid size ID + */ + client->errorValue = stuff->sizeID; + return BadValue; + } + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (has_rate) + rate = (int) stuff->rate; + else + rate = 0; + + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + client->errorValue = rate; + return BadValue; + } + } + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + rep.status = RRSetConfigFailed; + goto sendReply; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + pScrPriv->lastSetTime = time; + + /* + * Report Success + */ + rep.status = RRSetConfigSuccess; + +sendReply: + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + swapl(&rep.newConfigTimestamp, n); + swapl(&rep.root, n); + } + WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); + + return (client->noClientException); +} + +static int +ProcRRSelectInput (ClientPtr client) +{ + REQUEST(xRRSelectInputReq); + rrClientPriv(client); + RRTimesPtr pTimes; + WindowPtr pWin; + RREventPtr pRREvent, pNewRREvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH(xRRSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (RREventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, + SecurityWriteAccess); + + if (stuff->enable & (RRScreenChangeNotifyMask)) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + + if (pHead) + { + /* check for existing entry. */ + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + if (pRREvent->client == client) + return Success; + } + + /* build the entry */ + pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec)); + if (!pNewRREvent) + return BadAlloc; + pNewRREvent->next = 0; + pNewRREvent->client = client; + pNewRREvent->window = pWin; + pNewRREvent->mask = stuff->enable; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewRREvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent)) + 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 = (RREventPtr *) xalloc (sizeof (RREventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewRREvent->next = *pHead; + *pHead = pNewRREvent; + /* + * Now see if the client needs an event + */ + if (pScrPriv) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + TellChanged (pWin, (pointer) pScreen); + } + } + } + else if (stuff->enable == xFalse) + { + /* delete the interest */ + if (pHead) { + pNewRREvent = 0; + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (pRREvent->client == client) + break; + pNewRREvent = pRREvent; + } + if (pRREvent) { + FreeResource (pRREvent->clientResource, ClientType); + if (pNewRREvent) + pNewRREvent->next = pRREvent->next; + else + *pHead = pRREvent->next; + xfree (pRREvent); + } + } + } + else + { + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return ProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return ProcRRSetScreenConfig(client); + case X_RRSelectInput: + return ProcRRSelectInput(client); + case X_RRGetScreenInfo: + return ProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + +static int +SProcRRQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRRQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return ProcRRQueryVersion(client); +} + +static int +SProcRRGetScreenInfo (ClientPtr client) +{ + register int n; + REQUEST(xRRGetScreenInfoReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRGetScreenInfo(client); +} + +static int +SProcRRSetScreenConfig (ClientPtr client) +{ + register int n; + REQUEST(xRRSetScreenConfigReq); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + swaps (&stuff->rate, n); + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + } + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->sizeID, n); + swaps(&stuff->rotation, n); + return ProcRRSetScreenConfig(client); +} + +static int +SProcRRSelectInput (ClientPtr client) +{ + register int n; + REQUEST(xRRSelectInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRSelectInput(client); +} + + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return SProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return SProcRRSetScreenConfig(client); + case X_RRSelectInput: + return SProcRRSelectInput(client); + case X_RRGetScreenInfo: + return SProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + + +static Bool +RRScreenSizeMatches (RRScreenSizePtr a, + RRScreenSizePtr b) +{ + if (a->width != b->width) + return FALSE; + if (a->height != b->height) + return FALSE; + if (a->mmWidth != b->mmWidth) + return FALSE; + if (a->mmHeight != b->mmHeight) + return FALSE; + return TRUE; +} + +RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight) +{ + rrScrPriv (pScreen); + int i; + RRScreenSize tmp; + RRScreenSizePtr pNew; + + if (!pScrPriv) + return 0; + + tmp.width = width; + tmp.height= height; + tmp.mmWidth = mmWidth; + tmp.mmHeight = mmHeight; + tmp.pRates = 0; + tmp.nRates = 0; + tmp.nRatesInUse = 0; + tmp.referenced = TRUE; + tmp.oldReferenced = FALSE; + for (i = 0; i < pScrPriv->nSizes; i++) + if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i])) + { + pScrPriv->pSizes[i].referenced = TRUE; + return &pScrPriv->pSizes[i]; + } + pNew = xrealloc (pScrPriv->pSizes, + (pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); + if (!pNew) + return 0; + pNew[pScrPriv->nSizes++] = tmp; + pScrPriv->pSizes = pNew; + return &pNew[pScrPriv->nSizes-1]; +} + +Bool RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate) +{ + rrScrPriv(pScreen); + int i; + RRScreenRatePtr pNew, pRate; + + if (!pScrPriv) + return FALSE; + + for (i = 0; i < pSize->nRates; i++) + { + pRate = &pSize->pRates[i]; + if (pRate->rate == rate) + { + pRate->referenced = TRUE; + return TRUE; + } + } + + pNew = xrealloc (pSize->pRates, + (pSize->nRates + 1) * sizeof (RRScreenRate)); + if (!pNew) + return FALSE; + pRate = &pNew[pSize->nRates++]; + pRate->rate = rate; + pRate->referenced = TRUE; + pRate->oldReferenced = FALSE; + pSize->pRates = pNew; + return TRUE; +} + +void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + + pScrPriv->rotation = rotation; + pScrPriv->size = pSize - pScrPriv->pSizes; + pScrPriv->rate = rate; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXrender.c b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c new file mode 100644 index 000000000..20aca4619 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c @@ -0,0 +1,3048 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXrender.c" + +#else + +/* + * $XFree86: xc/programs/Xserver/render/render.c,v 1.26 2003/02/14 18:15:21 dawes Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include "render.h" +#include "renderproto.h" +#include "Xfuncproto.h" +#include "cursorstr.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#include "NXpicturestr.h" +#include "NXglyphstr.h" + +#include "Trap.h" + +#include "Render.h" +#include "Pixmaps.h" +#include "Options.h" +#include "Screen.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * From NXmiglyph.c. + */ + +void miGlyphExtents(int nlist, GlyphListPtr list, + GlyphPtr *glyphs, BoxPtr extents); + +/* + * Functions from Render.c. + */ + +int nxagentCursorSaveRenderInfo(ScreenPtr, CursorPtr); +void nxagentCursorPostSaveRenderInfo(CursorPtr, ScreenPtr, PicturePtr, int, int); +int nxagentRenderRealizeCursor(ScreenPtr, CursorPtr); +int nxagentCreatePicture(PicturePtr, Mask); +void nxagentDestroyPicture(PicturePtr pPicture); +void nxagentChangePicture(PicturePtr, Mask); +int nxagentChangePictureClip(PicturePtr, int, int, xRectangle *, int, int); +void nxagentComposite(CARD8, PicturePtr, PicturePtr, PicturePtr, INT16, INT16, + INT16, INT16, INT16, INT16, CARD16, CARD16); +void nxagentCompositeRects(CARD8, PicturePtr, xRenderColor *, int, xRectangle *); +void nxagentCreateGlyphSet(GlyphSetPtr glyphSet); +void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet); +void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph); +void nxagentFreeGlyphSet(GlyphSetPtr glyphSet); +void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform); +void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size, + pointer params, int nparams); +void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid *traps); + +/* + * The void pointer is actually a XGlyphElt8. + */ + +void nxagentGlyphs(CARD8, PicturePtr, PicturePtr, PictFormatPtr, + INT16, INT16, int, void *, int, GlyphPtr *); + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, +}; + +static void +RenderResetProc (ExtensionEntry *extEntry); + +static CARD8 RenderReqCode; +int RenderErrBase; +int RenderClientPrivateIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + RenderClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RenderClientPrivateIndex, + sizeof (RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + RenderResetProc, StandardMinorOpcode); + if (!extEntry) + return; + RenderReqCode = (CARD8) extEntry->base; + RenderErrBase = extEntry->errorBase; +} + +static void +RenderResetProc (ExtensionEntry *extEntry) +{ +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = nxagentRenderVersionMajor; + rep.minorVersion = nxagentRenderVersionMinor; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#if 0 +static int +VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + for (v = 0; v < pDepth->numVids; v++) + { + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + } + return 0; +} +#endif + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +extern char *ConnectionInfo; + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; + + extern int nxagentAlphaEnabled; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = nxagentAlphaEnabled ? pFormat->direct.alpha : 0; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + xfree (reply); + return client->noClientException; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + xfree(reply); + return (client->noClientException); +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len; + int error; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityWriteAccess); + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + nxagentCreatePicture(pPicture, stuff -> mask); + + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + int error; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + error = ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); + + nxagentChangePicture(pPicture, stuff->mask); + + return error; +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + int result; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + /* + * The original code used sizeof(xRenderChangePictureReq). + * This was harmless, as both structures have the same size. + * + * nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); + */ + nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq); + if (nr & 4) + return BadLength; + nr >>= 3; + result = SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); + nxagentChangePictureClip (pPicture, + CT_NONE, + nr, + (xRectangle *) &stuff[1], + (int)stuff -> xOrigin, + (int)stuff -> yOrigin); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + nxagentDestroyPicture(pPicture); + + FreeResource (stuff->picture, RT_NONE); + return(client->noClientException); +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + return FALSE; +} + +/* + * Check if both pictures have drawables which are + * virtual pixmaps. See the corresponding define + * in NXpicture.c + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#define nxagentCompositePredicate(pSrc, pDst) TRUE + +#else + +/* + * This is still under development. The final + * goal is to let pictures point to the real + * pixmaps instead of pointing to virtuals. + */ + +int nxagentCompositePredicate(PicturePtr pSrc, PicturePtr pDst) +{ + PixmapPtr pPixmap1; + PixmapPtr pPixmap2; + + pPixmap1 = (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pSrc -> pDrawable) : NULL); + + pPixmap2 = (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pDst -> pDrawable) : NULL); + + if (pPixmap1 == NULL || pPixmap2 == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 0.\n"); + #endif + + return FALSE; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 1.\n"); + #endif + + if (nxagentPixmapIsVirtual(pPixmap1) == 1 && + nxagentPixmapIsVirtual(pPixmap2) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 2.\n"); + #endif + + return TRUE; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 3.\n"); + #endif + + return FALSE; +} + +#endif + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen || + (pMask && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + if (nxagentCompositePredicate(pSrc, pDst)) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pMask, (void *) pDst); + #endif + + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + + #else + + if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP && + pDst -> pDrawable -> type == DRAWABLE_PIXMAP && + (!pMask || pMask -> pDrawable -> type == DRAWABLE_PIXMAP)) + { + PixmapPtr pVirtualPixmapSrc; + PixmapPtr pVirtualPixmapDst; + PixmapPtr pVirtualPixmapMask; + + PicturePtr pVirtualPictureSrc; + PicturePtr pVirtualPictureDst; + PicturePtr pVirtualPictureMask; + + pVirtualPixmapSrc = (PixmapPtr) pSrc -> pDrawable; + pVirtualPictureSrc = nxagentPixmapPriv(pVirtualPixmapSrc) -> pPicture; + + pVirtualPixmapDst = (PixmapPtr) pDst -> pDrawable; + pVirtualPictureDst = nxagentPixmapPriv(pVirtualPixmapDst) -> pPicture; + + if (pMask) + { + pVirtualPixmapMask = (PixmapPtr) pMask -> pDrawable; + pVirtualPictureMask = nxagentPixmapPriv(pVirtualPixmapMask) -> pPicture; + } + else + { + pVirtualPixmapMask = NULL; + pVirtualPictureMask = NULL; + } + + if (pVirtualPictureSrc && pVirtualPictureDst) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pVirtualPixmapSrc, (void *) pVirtualPixmapMask, + (void *) pVirtualPixmapDst); + #endif + + CompositePicture (stuff->op, + pVirtualPictureSrc, + pVirtualPictureMask, + pVirtualPictureDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + } + + #endif + + nxagentComposite (stuff -> op, + pSrc, + pMask, + pDst, + stuff -> xSrc, + stuff -> ySrc, + stuff -> xMask, + stuff -> yMask, + stuff -> xDst, + stuff -> yDst, + stuff -> width, + stuff -> height); + + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + { + if (nxagentCompositePredicate(pSrc, pDst)) + { + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + } + + nxagentTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + } + + return client->noClientException; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + format = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!format) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + + nxagentCreateGlyphSet(glyphSet); + + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->existing, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->existing; + return RenderErrBase + BadGlyphSet; + } + glyphSet->refcnt++; + + nxagentReferenceGlyphSet(glyphSet); + + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return client->noClientException; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityDestroyAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nxagentFreeGlyphSet(glyphSet); + + FreeResource (stuff->glyphset, RT_NONE); + return client->noClientException; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; +} GlyphNewRec, *GlyphNewPtr; + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs; + GlyphPtr glyph = NULL; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + int size; + int err = BadAlloc; + + int totSizeImages; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nglyphs = stuff->nglyphs; + if (nglyphs <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphNewPtr) ALLOCATE_LOCAL (nglyphs * sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + totSizeImages = 0; + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + + while (remain >= 0 && nglyphs) + { + glyph = AllocateGlyph (gi, glyphSet->fdepth); + if (!glyph) + { + err = BadAlloc; + goto bail; + } + + glyphs->glyph = glyph; + glyphs->id = *gids; + + size = glyph->size - sizeof (xGlyphInfo); + if (remain < size) + break; + memcpy ((CARD8 *) (glyph + 1), bits, size); + + if (size & 3) + size += 4 - (size & 3); + bits += size; + totSizeImages += size; + remain -= size; + gi++; + gids++; + glyphs++; + nglyphs--; + } + + if (nglyphs || remain) + { + err = BadLength; + goto bail; + } + nglyphs = stuff->nglyphs; + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + glyphs = glyphsBase; + while (nglyphs--) + AddGlyph (glyphSet, glyphs->glyph, glyphs->id); + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return client->noClientException; +bail: + while (glyphs != glyphsBase) + { + --glyphs; + xfree (glyphs->glyph); + } + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; + gids = (CARD32 *) (stuff + 1); + + nxagentFreeGlyphs(glyphSet, gids, nglyph); + + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return client->noClientException; +} + +typedef struct XGlyphElt8{ + GlyphSet glyphset; + _Xconst char *chars; + int nchars; + int xOff; + int yOff; +} XGlyphElt8; + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int n; + + XGlyphElt8 *elements, *elementsBase; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + + elementsBase = xalloc(nlist * sizeof(XGlyphElt8)); + if (!elementsBase) + return BadAlloc; + + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + elements = elementsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + #ifdef DEBUG + fprintf(stderr, "ProcRenderCompositeGlyphs: Glyphset change with base size [%d].\n", + size); + #endif + + if (buffer + sizeof (GlyphSet) < end) + { + gs = *(GlyphSet *) buffer; + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + gs, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = gs; + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + return RenderErrBase + BadGlyphSet; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + elements -> glyphset = glyphSet -> remoteID; + elements -> chars = (char *) buffer; + elements -> nchars = elt->len; + elements -> xOff = elt->deltax; + elements -> yOff = elt->deltay; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + elements++; + } + } + if (buffer > end) + return BadLength; + + /* + * We need to know the glyphs extents to synchronize + * the drawables involved in the composite text ope- + * ration. Also we need to synchronize only the back- + * ground of the text we are going to render, so the + * operations on the framebuffer must be executed + * after the X requests. + */ + + if (pFormat != NULL) + { + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents(nlist, listsBase, glyphsBase, nxagentGlyphsExtents); + } + + nxagentGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + elementsBase, + size, + glyphsBase); + + if (nxagentCompositePredicate(pSrc, pDst) == 1) + { + #ifdef TEST + fprintf(stderr, "ProcRenderCompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + CompositeGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + listsBase, + glyphsBase); + } + + if (nxagentGlyphsExtents != NullBox) + { + xfree(nxagentGlyphsExtents); + + nxagentGlyphsExtents = NullBox; + } + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + + xfree(elementsBase); + + return client->noClientException; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + ValidatePicture (pDst); + nxagentCompositeRects(stuff -> op, + pDst, + &stuff -> color, + things, + (xRectangle *) &stuff[1]); + + return client->noClientException; +} + +static void +SetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int ncolor; + + RealizeCursorProcPtr saveRealizeCursor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = xalloc (width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = (unsigned char *)xalloc(nbytes_mono); + if (!srcbits) + { + xfree (argbbits); + return (BadAlloc); + } + mskbits = (unsigned char *)xalloc(nbytes_mono); + if (!mskbits) + { + xfree(argbbits); + xfree(srcbits); + return (BadAlloc); + } + bzero ((char *) mskbits, nbytes_mono); + bzero ((char *) srcbits, nbytes_mono); + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); + if (!pPixmap) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + SetBit (mskline, x, a != 0); + SetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + SetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + SetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + xfree (argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + + /* + * This cursor uses RENDER, so we make sure + * that it is allocated in a way that allows + * the mi and dix layers to handle it but we + * later create it on the server by mirror- + * ing the RENDER operation we got from the + * client. + */ + + saveRealizeCursor = pScreen -> RealizeCursor; + + pScreen -> RealizeCursor = nxagentCursorSaveRenderInfo; + + pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0)); + + pScreen -> RealizeCursor = saveRealizeCursor; + + /* + * Store into the private data members the + * information needed to recreate it at + * reconnection. This is done in two steps + * as in the first step we don't have the + * picture info. + */ + + if (pCursor == NULL) + { + return BadAlloc; + } + + nxagentCursorPostSaveRenderInfo(pCursor, pScreen, pSrc, stuff -> x, stuff -> y); + + nxagentRenderRealizeCursor(pScreen, pCursor); + + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + int result; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); + + nxagentSetPictureTransform(pPicture, &stuff->transform); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j; + int len; + int total_bytes; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, SecurityReadAccess); + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < (int)reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + xfree (reply); + + return(client->noClientException); +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + name = (char *) (stuff + 1); + params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + + nxagentSetPictureFilter(pPicture, name, stuff->nbytes, params, nparams); + + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; + cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursors[i]) + { + xfree (cursors); + client->errorValue = elt->cursor; + return BadCursor; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); + xfree (cursors); + if (ret != Success) + return ret; + + for (i = 0; i < MAXSCREENS; i++) + { + pCursor -> devPriv[i] = NULL; + } + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + +static int +ProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*ProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register unsigned int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*SProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +unsigned long XRT_PICTURE; + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + xfree(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; +} + +#endif /* PANORAMIX */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXrender.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c.NX.original new file mode 100644 index 000000000..20aca4619 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c.NX.original @@ -0,0 +1,3048 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXrender.c" + +#else + +/* + * $XFree86: xc/programs/Xserver/render/render.c,v 1.26 2003/02/14 18:15:21 dawes Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include "render.h" +#include "renderproto.h" +#include "Xfuncproto.h" +#include "cursorstr.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#include "NXpicturestr.h" +#include "NXglyphstr.h" + +#include "Trap.h" + +#include "Render.h" +#include "Pixmaps.h" +#include "Options.h" +#include "Screen.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * From NXmiglyph.c. + */ + +void miGlyphExtents(int nlist, GlyphListPtr list, + GlyphPtr *glyphs, BoxPtr extents); + +/* + * Functions from Render.c. + */ + +int nxagentCursorSaveRenderInfo(ScreenPtr, CursorPtr); +void nxagentCursorPostSaveRenderInfo(CursorPtr, ScreenPtr, PicturePtr, int, int); +int nxagentRenderRealizeCursor(ScreenPtr, CursorPtr); +int nxagentCreatePicture(PicturePtr, Mask); +void nxagentDestroyPicture(PicturePtr pPicture); +void nxagentChangePicture(PicturePtr, Mask); +int nxagentChangePictureClip(PicturePtr, int, int, xRectangle *, int, int); +void nxagentComposite(CARD8, PicturePtr, PicturePtr, PicturePtr, INT16, INT16, + INT16, INT16, INT16, INT16, CARD16, CARD16); +void nxagentCompositeRects(CARD8, PicturePtr, xRenderColor *, int, xRectangle *); +void nxagentCreateGlyphSet(GlyphSetPtr glyphSet); +void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet); +void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph); +void nxagentFreeGlyphSet(GlyphSetPtr glyphSet); +void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform); +void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size, + pointer params, int nparams); +void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid *traps); + +/* + * The void pointer is actually a XGlyphElt8. + */ + +void nxagentGlyphs(CARD8, PicturePtr, PicturePtr, PictFormatPtr, + INT16, INT16, int, void *, int, GlyphPtr *); + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, +}; + +static void +RenderResetProc (ExtensionEntry *extEntry); + +static CARD8 RenderReqCode; +int RenderErrBase; +int RenderClientPrivateIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + RenderClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RenderClientPrivateIndex, + sizeof (RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + RenderResetProc, StandardMinorOpcode); + if (!extEntry) + return; + RenderReqCode = (CARD8) extEntry->base; + RenderErrBase = extEntry->errorBase; +} + +static void +RenderResetProc (ExtensionEntry *extEntry) +{ +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = nxagentRenderVersionMajor; + rep.minorVersion = nxagentRenderVersionMinor; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#if 0 +static int +VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + for (v = 0; v < pDepth->numVids; v++) + { + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + } + return 0; +} +#endif + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +extern char *ConnectionInfo; + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; + + extern int nxagentAlphaEnabled; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = nxagentAlphaEnabled ? pFormat->direct.alpha : 0; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + xfree (reply); + return client->noClientException; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + xfree(reply); + return (client->noClientException); +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len; + int error; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityWriteAccess); + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + nxagentCreatePicture(pPicture, stuff -> mask); + + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + int error; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + error = ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); + + nxagentChangePicture(pPicture, stuff->mask); + + return error; +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + int result; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + /* + * The original code used sizeof(xRenderChangePictureReq). + * This was harmless, as both structures have the same size. + * + * nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); + */ + nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq); + if (nr & 4) + return BadLength; + nr >>= 3; + result = SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); + nxagentChangePictureClip (pPicture, + CT_NONE, + nr, + (xRectangle *) &stuff[1], + (int)stuff -> xOrigin, + (int)stuff -> yOrigin); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + nxagentDestroyPicture(pPicture); + + FreeResource (stuff->picture, RT_NONE); + return(client->noClientException); +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + return FALSE; +} + +/* + * Check if both pictures have drawables which are + * virtual pixmaps. See the corresponding define + * in NXpicture.c + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#define nxagentCompositePredicate(pSrc, pDst) TRUE + +#else + +/* + * This is still under development. The final + * goal is to let pictures point to the real + * pixmaps instead of pointing to virtuals. + */ + +int nxagentCompositePredicate(PicturePtr pSrc, PicturePtr pDst) +{ + PixmapPtr pPixmap1; + PixmapPtr pPixmap2; + + pPixmap1 = (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pSrc -> pDrawable) : NULL); + + pPixmap2 = (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pDst -> pDrawable) : NULL); + + if (pPixmap1 == NULL || pPixmap2 == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 0.\n"); + #endif + + return FALSE; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 1.\n"); + #endif + + if (nxagentPixmapIsVirtual(pPixmap1) == 1 && + nxagentPixmapIsVirtual(pPixmap2) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 2.\n"); + #endif + + return TRUE; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 3.\n"); + #endif + + return FALSE; +} + +#endif + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen || + (pMask && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + if (nxagentCompositePredicate(pSrc, pDst)) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pMask, (void *) pDst); + #endif + + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + + #else + + if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP && + pDst -> pDrawable -> type == DRAWABLE_PIXMAP && + (!pMask || pMask -> pDrawable -> type == DRAWABLE_PIXMAP)) + { + PixmapPtr pVirtualPixmapSrc; + PixmapPtr pVirtualPixmapDst; + PixmapPtr pVirtualPixmapMask; + + PicturePtr pVirtualPictureSrc; + PicturePtr pVirtualPictureDst; + PicturePtr pVirtualPictureMask; + + pVirtualPixmapSrc = (PixmapPtr) pSrc -> pDrawable; + pVirtualPictureSrc = nxagentPixmapPriv(pVirtualPixmapSrc) -> pPicture; + + pVirtualPixmapDst = (PixmapPtr) pDst -> pDrawable; + pVirtualPictureDst = nxagentPixmapPriv(pVirtualPixmapDst) -> pPicture; + + if (pMask) + { + pVirtualPixmapMask = (PixmapPtr) pMask -> pDrawable; + pVirtualPictureMask = nxagentPixmapPriv(pVirtualPixmapMask) -> pPicture; + } + else + { + pVirtualPixmapMask = NULL; + pVirtualPictureMask = NULL; + } + + if (pVirtualPictureSrc && pVirtualPictureDst) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pVirtualPixmapSrc, (void *) pVirtualPixmapMask, + (void *) pVirtualPixmapDst); + #endif + + CompositePicture (stuff->op, + pVirtualPictureSrc, + pVirtualPictureMask, + pVirtualPictureDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + } + + #endif + + nxagentComposite (stuff -> op, + pSrc, + pMask, + pDst, + stuff -> xSrc, + stuff -> ySrc, + stuff -> xMask, + stuff -> yMask, + stuff -> xDst, + stuff -> yDst, + stuff -> width, + stuff -> height); + + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + { + if (nxagentCompositePredicate(pSrc, pDst)) + { + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + } + + nxagentTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + } + + return client->noClientException; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + format = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!format) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + + nxagentCreateGlyphSet(glyphSet); + + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->existing, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->existing; + return RenderErrBase + BadGlyphSet; + } + glyphSet->refcnt++; + + nxagentReferenceGlyphSet(glyphSet); + + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return client->noClientException; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityDestroyAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nxagentFreeGlyphSet(glyphSet); + + FreeResource (stuff->glyphset, RT_NONE); + return client->noClientException; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; +} GlyphNewRec, *GlyphNewPtr; + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs; + GlyphPtr glyph = NULL; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + int size; + int err = BadAlloc; + + int totSizeImages; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nglyphs = stuff->nglyphs; + if (nglyphs <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphNewPtr) ALLOCATE_LOCAL (nglyphs * sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + totSizeImages = 0; + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + + while (remain >= 0 && nglyphs) + { + glyph = AllocateGlyph (gi, glyphSet->fdepth); + if (!glyph) + { + err = BadAlloc; + goto bail; + } + + glyphs->glyph = glyph; + glyphs->id = *gids; + + size = glyph->size - sizeof (xGlyphInfo); + if (remain < size) + break; + memcpy ((CARD8 *) (glyph + 1), bits, size); + + if (size & 3) + size += 4 - (size & 3); + bits += size; + totSizeImages += size; + remain -= size; + gi++; + gids++; + glyphs++; + nglyphs--; + } + + if (nglyphs || remain) + { + err = BadLength; + goto bail; + } + nglyphs = stuff->nglyphs; + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + glyphs = glyphsBase; + while (nglyphs--) + AddGlyph (glyphSet, glyphs->glyph, glyphs->id); + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return client->noClientException; +bail: + while (glyphs != glyphsBase) + { + --glyphs; + xfree (glyphs->glyph); + } + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; + gids = (CARD32 *) (stuff + 1); + + nxagentFreeGlyphs(glyphSet, gids, nglyph); + + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return client->noClientException; +} + +typedef struct XGlyphElt8{ + GlyphSet glyphset; + _Xconst char *chars; + int nchars; + int xOff; + int yOff; +} XGlyphElt8; + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int n; + + XGlyphElt8 *elements, *elementsBase; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + + elementsBase = xalloc(nlist * sizeof(XGlyphElt8)); + if (!elementsBase) + return BadAlloc; + + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + elements = elementsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + #ifdef DEBUG + fprintf(stderr, "ProcRenderCompositeGlyphs: Glyphset change with base size [%d].\n", + size); + #endif + + if (buffer + sizeof (GlyphSet) < end) + { + gs = *(GlyphSet *) buffer; + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + gs, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = gs; + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + return RenderErrBase + BadGlyphSet; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + elements -> glyphset = glyphSet -> remoteID; + elements -> chars = (char *) buffer; + elements -> nchars = elt->len; + elements -> xOff = elt->deltax; + elements -> yOff = elt->deltay; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + elements++; + } + } + if (buffer > end) + return BadLength; + + /* + * We need to know the glyphs extents to synchronize + * the drawables involved in the composite text ope- + * ration. Also we need to synchronize only the back- + * ground of the text we are going to render, so the + * operations on the framebuffer must be executed + * after the X requests. + */ + + if (pFormat != NULL) + { + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents(nlist, listsBase, glyphsBase, nxagentGlyphsExtents); + } + + nxagentGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + elementsBase, + size, + glyphsBase); + + if (nxagentCompositePredicate(pSrc, pDst) == 1) + { + #ifdef TEST + fprintf(stderr, "ProcRenderCompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + CompositeGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + listsBase, + glyphsBase); + } + + if (nxagentGlyphsExtents != NullBox) + { + xfree(nxagentGlyphsExtents); + + nxagentGlyphsExtents = NullBox; + } + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + + xfree(elementsBase); + + return client->noClientException; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + ValidatePicture (pDst); + nxagentCompositeRects(stuff -> op, + pDst, + &stuff -> color, + things, + (xRectangle *) &stuff[1]); + + return client->noClientException; +} + +static void +SetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int ncolor; + + RealizeCursorProcPtr saveRealizeCursor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = xalloc (width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = (unsigned char *)xalloc(nbytes_mono); + if (!srcbits) + { + xfree (argbbits); + return (BadAlloc); + } + mskbits = (unsigned char *)xalloc(nbytes_mono); + if (!mskbits) + { + xfree(argbbits); + xfree(srcbits); + return (BadAlloc); + } + bzero ((char *) mskbits, nbytes_mono); + bzero ((char *) srcbits, nbytes_mono); + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); + if (!pPixmap) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + SetBit (mskline, x, a != 0); + SetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + SetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + SetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + xfree (argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + + /* + * This cursor uses RENDER, so we make sure + * that it is allocated in a way that allows + * the mi and dix layers to handle it but we + * later create it on the server by mirror- + * ing the RENDER operation we got from the + * client. + */ + + saveRealizeCursor = pScreen -> RealizeCursor; + + pScreen -> RealizeCursor = nxagentCursorSaveRenderInfo; + + pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0)); + + pScreen -> RealizeCursor = saveRealizeCursor; + + /* + * Store into the private data members the + * information needed to recreate it at + * reconnection. This is done in two steps + * as in the first step we don't have the + * picture info. + */ + + if (pCursor == NULL) + { + return BadAlloc; + } + + nxagentCursorPostSaveRenderInfo(pCursor, pScreen, pSrc, stuff -> x, stuff -> y); + + nxagentRenderRealizeCursor(pScreen, pCursor); + + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + int result; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); + + nxagentSetPictureTransform(pPicture, &stuff->transform); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j; + int len; + int total_bytes; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, SecurityReadAccess); + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < (int)reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + xfree (reply); + + return(client->noClientException); +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + name = (char *) (stuff + 1); + params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + + nxagentSetPictureFilter(pPicture, name, stuff->nbytes, params, nparams); + + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; + cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursors[i]) + { + xfree (cursors); + client->errorValue = elt->cursor; + return BadCursor; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); + xfree (cursors); + if (ret != Success) + return ret; + + for (i = 0; i < MAXSCREENS; i++) + { + pCursor -> devPriv[i] = NULL; + } + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + +static int +ProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*ProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register unsigned int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*SProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +unsigned long XRT_PICTURE; + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + xfree(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; +} + +#endif /* PANORAMIX */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXrender.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c.XF86.original new file mode 100644 index 000000000..a4f90ea77 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c.XF86.original @@ -0,0 +1,2584 @@ +/* + * $XFree86: xc/programs/Xserver/render/render.c,v 1.26 2003/02/14 18:15:21 dawes Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include "render.h" +#include "renderproto.h" +#include "picturestr.h" +#include "glyphstr.h" +#include "Xfuncproto.h" +#include "cursorstr.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, +}; + +static void +RenderResetProc (ExtensionEntry *extEntry); + +static CARD8 RenderReqCode; +int RenderErrBase; +int RenderClientPrivateIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + RenderClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RenderClientPrivateIndex, + sizeof (RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + RenderResetProc, StandardMinorOpcode); + if (!extEntry) + return; + RenderReqCode = (CARD8) extEntry->base; + RenderErrBase = extEntry->errorBase; +} + +static void +RenderResetProc (ExtensionEntry *extEntry) +{ +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RENDER_MAJOR; + rep.minorVersion = RENDER_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#if 0 +static int +VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + for (v = 0; v < pDepth->numVids; v++) + { + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + } + return 0; +} +#endif + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +extern char *ConnectionInfo; + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = pFormat->direct.alpha; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + xfree (reply); + return client->noClientException; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + xfree(reply); + return (client->noClientException); +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len; + int error; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityWriteAccess); + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + int result; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); + if (nr & 4) + return BadLength; + nr >>= 3; + result = SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + FreeResource (stuff->picture, RT_NONE); + return(client->noClientException); +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + return FALSE; +} + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen || + (pMask && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + format = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!format) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->existing, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->existing; + return RenderErrBase + BadGlyphSet; + } + glyphSet->refcnt++; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return client->noClientException; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityDestroyAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + FreeResource (stuff->glyphset, RT_NONE); + return client->noClientException; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; +} GlyphNewRec, *GlyphNewPtr; + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs; + GlyphPtr glyph; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + int size; + int err = BadAlloc; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nglyphs = stuff->nglyphs; + if (nglyphs <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphNewPtr) ALLOCATE_LOCAL (nglyphs * sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + while (remain >= 0 && nglyphs) + { + glyph = AllocateGlyph (gi, glyphSet->fdepth); + if (!glyph) + { + err = BadAlloc; + goto bail; + } + + glyphs->glyph = glyph; + glyphs->id = *gids; + + size = glyph->size - sizeof (xGlyphInfo); + if (remain < size) + break; + memcpy ((CARD8 *) (glyph + 1), bits, size); + + if (size & 3) + size += 4 - (size & 3); + bits += size; + remain -= size; + gi++; + gids++; + glyphs++; + nglyphs--; + } + if (nglyphs || remain) + { + err = BadLength; + goto bail; + } + nglyphs = stuff->nglyphs; + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + glyphs = glyphsBase; + while (nglyphs--) + AddGlyph (glyphSet, glyphs->glyph, glyphs->id); + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return client->noClientException; +bail: + while (glyphs != glyphsBase) + { + --glyphs; + xfree (glyphs->glyph); + } + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; + gids = (CARD32 *) (stuff + 1); + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return client->noClientException; +} + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int n; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + if (buffer + sizeof (GlyphSet) < end) + { + gs = *(GlyphSet *) buffer; + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + gs, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = gs; + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + return RenderErrBase + BadGlyphSet; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + } + } + if (buffer > end) + return BadLength; + + CompositeGlyphs (stuff->op, + pSrc, + pDst, + pFormat, + stuff->xSrc, + stuff->ySrc, + nlist, + listsBase, + glyphsBase); + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + + return client->noClientException; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + return client->noClientException; +} + +static void +SetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int ncolor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = xalloc (width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = (unsigned char *)xalloc(nbytes_mono); + if (!srcbits) + { + xfree (argbbits); + return (BadAlloc); + } + mskbits = (unsigned char *)xalloc(nbytes_mono); + if (!mskbits) + { + xfree(argbbits); + xfree(srcbits); + return (BadAlloc); + } + bzero ((char *) mskbits, nbytes_mono); + bzero ((char *) srcbits, nbytes_mono); + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); + if (!pPixmap) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture); + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + SetBit (mskline, x, a != 0); + SetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + SetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + SetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + xfree (argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0)); + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + int result; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j; + int len; + int total_bytes; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, SecurityReadAccess); + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + xfree (reply); + + return(client->noClientException); +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + name = (char *) (stuff + 1); + params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; + cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursors[i]) + { + xfree (cursors); + client->errorValue = elt->cursor; + return BadCursor; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); + xfree (cursors); + if (ret != Success) + return ret; + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + +static int +ProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*ProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*SProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +unsigned long XRT_PICTURE; + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + xfree(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; +} + +#endif /* PANORAMIX */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXresource.c b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c new file mode 100644 index 000000000..0c81c81ef --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c @@ -0,0 +1,1103 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXresource.c" + +#else + +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* $Xorg: resource.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ + + +/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ +/* $XFree86: xc/programs/Xserver/dix/resource.c,v 3.12 2002/03/06 21:13:38 mvojkovi Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include "dixfont.h" +#include "colormap.h" +#include "inputstr.h" +#include "dixevents.h" +#include "dixgrabs.h" +#include "cursor.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include + +#ifdef NXAGENT_SERVER + +#include "Agent.h" +#include "Font.h" +#include "Pixmaps.h" +#include "GCs.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#endif + +static void RebuildTable( +#if NeedFunctionPrototypes + int /*client*/ +#endif +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +#ifdef XResExtension + +Atom * ResourceNames = NULL; + +void RegisterResourceName (RESTYPE type, char *name) +{ + ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); +} + +#endif + +RESTYPE +CreateNewResourceType(deleteFunc) + DeleteType deleteFunc; +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); + if(!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(client) + ClientPtr client; +{ + register int i, j; + + if (client == serverClient) + { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + +#ifdef XResExtension + if(ResourceNames) + xfree(ResourceNames); + ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); + if(!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +#if NeedFunctionPrototypes +AvailableID( + register int client, + register XID id, + register XID maxid, + register XID goodid) +#else +AvailableID(client, id, maxid, goodid) + register int client; + register XID id, maxid, goodid; +#endif +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +void +GetXIDRange(client, server, minp, maxp) + int client; + Bool server; + XID *minp, *maxp; +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/* GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +unsigned int +GetXIDList(pClient, count, pids) + ClientPtr pClient; + unsigned int count; + XID *pids; +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +XID +FakeClientID(client) + register int client; +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +#ifdef NXAGENT_SERVER + +int nxagentFindClientResource(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + int i; + + for (i = 0; i < clientTable[client].buckets; i++) + { + resources = clientTable[client].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == type && pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentFindClientResource: Found resource [%p] type [%lu] " + "for client [%d].\n", (void *) value, + pResource -> type, client); + #endif + + return 1; + } + } + } + + return 0; +} + +int nxagentSwitchResourceType(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + RESTYPE internalType = 0; + + int i; + + if (type == RT_PIXMAP) + { + internalType = RT_NX_PIXMAP; + } + else if (type == RT_GC) + { + internalType = RT_NX_GC; + } + else if (type == RT_FONT) + { + internalType = RT_NX_FONT; + } + else + { + return 0; + } + + if (client == serverClient -> index) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Requesting client is [%d]. Skipping the resource switch.\n", + client); + #endif + + return 0; + } + + for (i = 0; i < clientTable[serverClient -> index].buckets; i++) + { + resources = clientTable[serverClient -> index].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == internalType && + pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Changing resource [%p] type from [%lu] to " + "[%lu] for server client [%d].\n", (void *) value, + (unsigned long) pResource -> type, (unsigned long) type, serverClient -> index); + #endif + + FreeResource(pResource -> id, RT_NONE); + + return 1; + } + } + } + + return 0; +} + +#endif + +Bool +AddResource(id, type, value) + XID id; + RESTYPE type; + pointer value; +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%x, %x, %x), client=%d \n", + id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + +#ifdef NXAGENT_SERVER + + nxagentSwitchResourceType(client, type, value); + + #ifdef TEST + fprintf(stderr, "AddResource: Adding resource for client [%d] type [%lu] value [%p] id [%lu].\n", + client, (unsigned long) type, (void *) value, (unsigned long) id); + #endif + +#endif + + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(client) + int client; +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +void +FreeResource(id, skipDeleteFuncType) + XID id; + RESTYPE skipDeleteFuncType; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + FatalError("Freeing resource id=%X which isn't there", id); +} + + +void +FreeResourceByType(id, type, skipFree) + XID id; + RESTYPE type; + Bool skipFree; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +Bool +ChangeResourceValue (id, rtype, value) + XID id; + RESTYPE rtype; + pointer value; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +void +FindClientResourcesByType( + ClientPtr client, + RESTYPE type, + FindResType func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +void +FindAllClientResources( + ClientPtr client, + FindAllRes func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + elements = *eltptr; + (*func)(this->value, this->id, this->type, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } +} + + +pointer +LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata +){ + ResourcePtr *resources; + ResourcePtr this; + int i; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + for (i = 0; i < clientTable[client->index].buckets; i++) { + for (this = resources[i]; this; this = this->next) { + if (!type || this->type == type) { + if((*func)(this->value, this->id, cdata)) + return this->value; + } + } + } + return NULL; +} + + +void +FreeClientNeverRetainResources(ClientPtr client) +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(client) + ClientPtr client; +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].resources = NULL; + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +Bool +LegalNewID(id, client) + XID id; + register ClientPtr client; +{ + +#ifdef PANORAMIX + XID minid, maxid; + + if (!noPanoramiXExtension) { + minid = client->clientAsMask | (client->index ? + SERVER_BIT : SERVER_MINID); + maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; + if ((id >= minid) && (id <= maxid)) + return TRUE; + } +#endif /* PANORAMIX */ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +#ifdef XCSECURITY + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +pointer +SecurityLookupIDByType(client, id, rtype, mode) + ClientPtr client; + XID id; + RESTYPE rtype; + Mask mode; +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert( (rtype & TypeMask) <= lastResourceType); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, rtype, mode, retval); + return retval; +} + + +pointer +SecurityLookupIDByClass(client, id, classes, mode) + ClientPtr client; + XID id; + RESTYPE classes; + Mask mode; +{ + int cid; + register ResourcePtr res = NULL; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert (classes >= lastResourceClass); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, res->type, mode, retval); + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +/* + * LookupIDByType returns the object with the given id and type, else NULL. + */ +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + return res->value; + } + return (pointer)NULL; +} + +/* + * LookupIDByClass returns the object with the given id and any one of the + * given classes, else NULL. + */ +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + return res->value; + } + return (pointer)NULL; +} + +#endif /* XCSECURITY */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXresource.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c.NX.original new file mode 100644 index 000000000..0c81c81ef --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c.NX.original @@ -0,0 +1,1103 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXresource.c" + +#else + +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* $Xorg: resource.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ + + +/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ +/* $XFree86: xc/programs/Xserver/dix/resource.c,v 3.12 2002/03/06 21:13:38 mvojkovi Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include "dixfont.h" +#include "colormap.h" +#include "inputstr.h" +#include "dixevents.h" +#include "dixgrabs.h" +#include "cursor.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include + +#ifdef NXAGENT_SERVER + +#include "Agent.h" +#include "Font.h" +#include "Pixmaps.h" +#include "GCs.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#endif + +static void RebuildTable( +#if NeedFunctionPrototypes + int /*client*/ +#endif +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +#ifdef XResExtension + +Atom * ResourceNames = NULL; + +void RegisterResourceName (RESTYPE type, char *name) +{ + ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); +} + +#endif + +RESTYPE +CreateNewResourceType(deleteFunc) + DeleteType deleteFunc; +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); + if(!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(client) + ClientPtr client; +{ + register int i, j; + + if (client == serverClient) + { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + +#ifdef XResExtension + if(ResourceNames) + xfree(ResourceNames); + ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); + if(!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +#if NeedFunctionPrototypes +AvailableID( + register int client, + register XID id, + register XID maxid, + register XID goodid) +#else +AvailableID(client, id, maxid, goodid) + register int client; + register XID id, maxid, goodid; +#endif +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +void +GetXIDRange(client, server, minp, maxp) + int client; + Bool server; + XID *minp, *maxp; +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/* GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +unsigned int +GetXIDList(pClient, count, pids) + ClientPtr pClient; + unsigned int count; + XID *pids; +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +XID +FakeClientID(client) + register int client; +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +#ifdef NXAGENT_SERVER + +int nxagentFindClientResource(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + int i; + + for (i = 0; i < clientTable[client].buckets; i++) + { + resources = clientTable[client].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == type && pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentFindClientResource: Found resource [%p] type [%lu] " + "for client [%d].\n", (void *) value, + pResource -> type, client); + #endif + + return 1; + } + } + } + + return 0; +} + +int nxagentSwitchResourceType(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + RESTYPE internalType = 0; + + int i; + + if (type == RT_PIXMAP) + { + internalType = RT_NX_PIXMAP; + } + else if (type == RT_GC) + { + internalType = RT_NX_GC; + } + else if (type == RT_FONT) + { + internalType = RT_NX_FONT; + } + else + { + return 0; + } + + if (client == serverClient -> index) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Requesting client is [%d]. Skipping the resource switch.\n", + client); + #endif + + return 0; + } + + for (i = 0; i < clientTable[serverClient -> index].buckets; i++) + { + resources = clientTable[serverClient -> index].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == internalType && + pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Changing resource [%p] type from [%lu] to " + "[%lu] for server client [%d].\n", (void *) value, + (unsigned long) pResource -> type, (unsigned long) type, serverClient -> index); + #endif + + FreeResource(pResource -> id, RT_NONE); + + return 1; + } + } + } + + return 0; +} + +#endif + +Bool +AddResource(id, type, value) + XID id; + RESTYPE type; + pointer value; +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%x, %x, %x), client=%d \n", + id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + +#ifdef NXAGENT_SERVER + + nxagentSwitchResourceType(client, type, value); + + #ifdef TEST + fprintf(stderr, "AddResource: Adding resource for client [%d] type [%lu] value [%p] id [%lu].\n", + client, (unsigned long) type, (void *) value, (unsigned long) id); + #endif + +#endif + + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(client) + int client; +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +void +FreeResource(id, skipDeleteFuncType) + XID id; + RESTYPE skipDeleteFuncType; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + FatalError("Freeing resource id=%X which isn't there", id); +} + + +void +FreeResourceByType(id, type, skipFree) + XID id; + RESTYPE type; + Bool skipFree; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +Bool +ChangeResourceValue (id, rtype, value) + XID id; + RESTYPE rtype; + pointer value; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +void +FindClientResourcesByType( + ClientPtr client, + RESTYPE type, + FindResType func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +void +FindAllClientResources( + ClientPtr client, + FindAllRes func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + elements = *eltptr; + (*func)(this->value, this->id, this->type, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } +} + + +pointer +LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata +){ + ResourcePtr *resources; + ResourcePtr this; + int i; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + for (i = 0; i < clientTable[client->index].buckets; i++) { + for (this = resources[i]; this; this = this->next) { + if (!type || this->type == type) { + if((*func)(this->value, this->id, cdata)) + return this->value; + } + } + } + return NULL; +} + + +void +FreeClientNeverRetainResources(ClientPtr client) +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(client) + ClientPtr client; +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].resources = NULL; + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +Bool +LegalNewID(id, client) + XID id; + register ClientPtr client; +{ + +#ifdef PANORAMIX + XID minid, maxid; + + if (!noPanoramiXExtension) { + minid = client->clientAsMask | (client->index ? + SERVER_BIT : SERVER_MINID); + maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; + if ((id >= minid) && (id <= maxid)) + return TRUE; + } +#endif /* PANORAMIX */ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +#ifdef XCSECURITY + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +pointer +SecurityLookupIDByType(client, id, rtype, mode) + ClientPtr client; + XID id; + RESTYPE rtype; + Mask mode; +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert( (rtype & TypeMask) <= lastResourceType); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, rtype, mode, retval); + return retval; +} + + +pointer +SecurityLookupIDByClass(client, id, classes, mode) + ClientPtr client; + XID id; + RESTYPE classes; + Mask mode; +{ + int cid; + register ResourcePtr res = NULL; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert (classes >= lastResourceClass); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, res->type, mode, retval); + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +/* + * LookupIDByType returns the object with the given id and type, else NULL. + */ +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + return res->value; + } + return (pointer)NULL; +} + +/* + * LookupIDByClass returns the object with the given id and any one of the + * given classes, else NULL. + */ +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + return res->value; + } + return (pointer)NULL; +} + +#endif /* XCSECURITY */ + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXresource.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c.XF86.original new file mode 100644 index 000000000..d17586a77 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c.XF86.original @@ -0,0 +1,975 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* $Xorg: resource.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ + + +/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ +/* $XFree86: xc/programs/Xserver/dix/resource.c,v 3.12 2002/03/06 21:13:38 mvojkovi Exp $ */ + +#define NEED_EVENTS +#include "X.h" +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include "dixfont.h" +#include "colormap.h" +#include "inputstr.h" +#include "dixevents.h" +#include "dixgrabs.h" +#include "cursor.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include + +static void RebuildTable( +#if NeedFunctionPrototypes + int /*client*/ +#endif +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +#ifdef XResExtension + +Atom * ResourceNames = NULL; + +void RegisterResourceName (RESTYPE type, char *name) +{ + ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); +} + +#endif + +RESTYPE +CreateNewResourceType(deleteFunc) + DeleteType deleteFunc; +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); + if(!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(client) + ClientPtr client; +{ + register int i, j; + + if (client == serverClient) + { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + +#ifdef XResExtension + if(ResourceNames) + xfree(ResourceNames); + ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); + if(!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +#if NeedFunctionPrototypes +AvailableID( + register int client, + register XID id, + register XID maxid, + register XID goodid) +#else +AvailableID(client, id, maxid, goodid) + register int client; + register XID id, maxid, goodid; +#endif +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +void +GetXIDRange(client, server, minp, maxp) + int client; + Bool server; + XID *minp, *maxp; +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/* GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +unsigned int +GetXIDList(pClient, count, pids) + ClientPtr pClient; + unsigned int count; + XID *pids; +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +XID +FakeClientID(client) + register int client; +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +Bool +AddResource(id, type, value) + XID id; + RESTYPE type; + pointer value; +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%x, %x, %x), client=%d \n", + id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(client) + int client; +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +void +FreeResource(id, skipDeleteFuncType) + XID id; + RESTYPE skipDeleteFuncType; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + FatalError("Freeing resource id=%X which isn't there", id); +} + + +void +FreeResourceByType(id, type, skipFree) + XID id; + RESTYPE type; + Bool skipFree; +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +Bool +ChangeResourceValue (id, rtype, value) + XID id; + RESTYPE rtype; + pointer value; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +void +FindClientResourcesByType( + ClientPtr client, + RESTYPE type, + FindResType func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +void +FindAllClientResources( + ClientPtr client, + FindAllRes func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + elements = *eltptr; + (*func)(this->value, this->id, this->type, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } +} + + +pointer +LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata +){ + ResourcePtr *resources; + ResourcePtr this; + int i; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + for (i = 0; i < clientTable[client->index].buckets; i++) { + for (this = resources[i]; this; this = this->next) { + if (!type || this->type == type) { + if((*func)(this->value, this->id, cdata)) + return this->value; + } + } + } + return NULL; +} + + +void +FreeClientNeverRetainResources(ClientPtr client) +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(client) + ClientPtr client; +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].resources = NULL; + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +Bool +LegalNewID(id, client) + XID id; + register ClientPtr client; +{ + +#ifdef PANORAMIX + XID minid, maxid; + + if (!noPanoramiXExtension) { + minid = client->clientAsMask | (client->index ? + SERVER_BIT : SERVER_MINID); + maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; + if ((id >= minid) && (id <= maxid)) + return TRUE; + } +#endif /* PANORAMIX */ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +#ifdef XCSECURITY + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +pointer +SecurityLookupIDByType(client, id, rtype, mode) + ClientPtr client; + XID id; + RESTYPE rtype; + Mask mode; +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert( (rtype & TypeMask) <= lastResourceType); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, rtype, mode, retval); + return retval; +} + + +pointer +SecurityLookupIDByClass(client, id, classes, mode) + ClientPtr client; + XID id; + RESTYPE classes; + Mask mode; +{ + int cid; + register ResourcePtr res = NULL; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert (classes >= lastResourceClass); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, res->type, mode, retval); + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +/* + * LookupIDByType returns the object with the given id and type, else NULL. + */ +pointer +LookupIDByType(id, rtype) + XID id; + RESTYPE rtype; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + return res->value; + } + return (pointer)NULL; +} + +/* + * LookupIDByClass returns the object with the given id and any one of the + * given classes, else NULL. + */ +pointer +LookupIDByClass(id, classes) + XID id; + RESTYPE classes; +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + return res->value; + } + return (pointer)NULL; +} + +#endif /* XCSECURITY */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXshm.c b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c new file mode 100644 index 000000000..e70415a7d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c @@ -0,0 +1,1425 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXshm.c" + +#else + +/* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.36 2002/04/03 19:51:11 herrb Exp $ */ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#include +#ifndef Lynx +#include +#include +#else +#include +#include +#endif +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include "shmstr.h" +#include "Xfuncproto.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "Trap.h" +#include "Agent.h" +#include "Drawable.h" +#include "Pixmaps.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +extern void fbGetImage(DrawablePtr pDrw, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + +extern void fbPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *pImage); + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( +#if NeedFunctionPrototypes + pointer /* value */, + XID /* shmseg */ +#endif + ); +static void ShmResetProc( +#if NeedFunctionPrototypes + ExtensionEntry * /* extEntry */ +#endif + ); +static void SShmCompletionEvent( +#if NeedFunctionPrototypes + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ +#endif + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +#ifdef PIXPRIV +static int shmPixmapPrivate; +#endif +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall() +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + /* Clean up */ + if (shmid != -1) + { + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} +#endif + +void +ShmExtensionInit() +{ + ExtensionEntry *extEntry; + int i; + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + if (nxagentOption(SharedMemory) == False) + { + return; + } + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + sharedPixmaps = nxagentOption(SharedPixmaps); + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + { + #ifdef TEST + fprintf(stderr, "ShmExtensionInit: Registering shmFuncs as miFuncs.\n"); + #endif + shmFuncs[i] = &miFuncs; + } + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; + if (sharedPixmaps) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } +#ifdef PIXPRIV + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } +#endif + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs(pScreen, funcs) + ScreenPtr pScreen; + ShmFuncsPtr funcs; +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat(pScreen, format) + ScreenPtr pScreen; + int format; +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; +#ifdef PIXPRIV + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; +#else + char *base = (char *) pPixmap->devPrivate.ptr; + + if (base != (pointer) (pPixmap + 1)) + { + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) + { + if (shmdesc->addr <= base && base <= shmdesc->addr + shmdesc->size) + break; + } + } + else + shmdesc = 0; +#endif + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + #ifdef TEST + fprintf(stderr, "ShmRegisterFbFuncs: Registering shmFuncs as fbFuncs.\n"); + #endif + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + xfree(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + nxagentShmTrap = 0; + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + { + nxagentShmTrap = 1; + return; + } + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + nxagentShmTrap = 1; + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); + nxagentShmTrap = 1; +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + int length; + char *newdata; + extern int nxagentImageLength(int, int, int, int, int); + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Called with drawable at [%p] GC at [%p] data at [%p].\n", + (void *) dst, (void *) pGC, (void *) data); + #endif + + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + + /* + * We updated the internal framebuffer, + * now we want to go on the real X. + */ + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Realizing the PutImage with depth [%d] " + " format [%d] w [%d] h [%d] sx [%d] sy [%d] sw [%d] " + " sh [%d] dx [%d].\n", depth, format, w, h, + sx, sy, sw, sh, dx); + #endif + + length = nxagentImageLength(sw, sh, format, 0, depth); + + if ((newdata = xalloc(length)) != NULL) + { + fbGetImage((DrawablePtr) pPixmap, sx, sy, sw, sh, format, AllPlanes, newdata); + (*pGC->ops->PutImage)(dst, pGC, depth, dx, dy, sw, sh, 0, format, newdata); + + xfree(newdata); + } + else + { + #ifdef WARNING + fprintf(stderr, "fbShmPutImage: WARNING! Data allocation failed.\n"); + #endif + } + + FreeScratchPixmapHeader(pPixmap); + } + else + { + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Calling miShmPutImage().\n"); + #endif + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); + } +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(register ClientPtr client) +{ + int j, result = 0, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != client->noClientException) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + + if (client->swapped) { + register int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static int +ProcPanoramiXShmCreatePixmap(client) + register ClientPtr client; +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + PanoramiXRes *newPix; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = (client->noClientException); + + FOR_NSCREENS(j) { + pScreen = screenInfo.screens[j]; + + pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + xfree(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Format [%d] srcX [%d] srcY [%d], " + "totalWidth [%d] totalHeight [%d]\n", stuff->format, stuff->srcX, + stuff->srcY, stuff->totalWidth, stuff->totalHeight); + #endif + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Calling (*shmFuncs[pDraw->pScreen->myNum]->PutImage)().\n"); + #endif + + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + stuff->offset); + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else + { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + nxagentShmPixmapTrap = 1; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, width, height, depth); + + if (!pPixmap) + { + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + #ifdef TEST + fprintf(stderr,"fbShmCreatePixmap: Width [%d] Height [%d] Depth [%d]\n", width, height, depth); + #endif + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) + { + #ifdef WARNING + fprintf(stderr,"fbShmCreatePixmap: Return Null Pixmap.\n"); + #endif + + (*pScreen->DestroyPixmap)(pPixmap); + + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + nxagentShmPixmapTrap = 0; + + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return(client->noClientException); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + { + result = ProcPanoramiXShmPutImage(client); + + nxagentShmTrap = 0; + + return result; + } +#endif + + result = ProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Returning from ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + + result = SProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Returning from SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXshm.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c.NX.original new file mode 100644 index 000000000..e70415a7d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c.NX.original @@ -0,0 +1,1425 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXshm.c" + +#else + +/* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.36 2002/04/03 19:51:11 herrb Exp $ */ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#include +#ifndef Lynx +#include +#include +#else +#include +#include +#endif +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include "shmstr.h" +#include "Xfuncproto.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "Trap.h" +#include "Agent.h" +#include "Drawable.h" +#include "Pixmaps.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +extern void fbGetImage(DrawablePtr pDrw, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + +extern void fbPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *pImage); + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( +#if NeedFunctionPrototypes + pointer /* value */, + XID /* shmseg */ +#endif + ); +static void ShmResetProc( +#if NeedFunctionPrototypes + ExtensionEntry * /* extEntry */ +#endif + ); +static void SShmCompletionEvent( +#if NeedFunctionPrototypes + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ +#endif + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +#ifdef PIXPRIV +static int shmPixmapPrivate; +#endif +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall() +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + /* Clean up */ + if (shmid != -1) + { + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} +#endif + +void +ShmExtensionInit() +{ + ExtensionEntry *extEntry; + int i; + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + if (nxagentOption(SharedMemory) == False) + { + return; + } + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + sharedPixmaps = nxagentOption(SharedPixmaps); + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + { + #ifdef TEST + fprintf(stderr, "ShmExtensionInit: Registering shmFuncs as miFuncs.\n"); + #endif + shmFuncs[i] = &miFuncs; + } + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; + if (sharedPixmaps) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } +#ifdef PIXPRIV + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } +#endif + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs(pScreen, funcs) + ScreenPtr pScreen; + ShmFuncsPtr funcs; +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat(pScreen, format) + ScreenPtr pScreen; + int format; +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; +#ifdef PIXPRIV + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; +#else + char *base = (char *) pPixmap->devPrivate.ptr; + + if (base != (pointer) (pPixmap + 1)) + { + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) + { + if (shmdesc->addr <= base && base <= shmdesc->addr + shmdesc->size) + break; + } + } + else + shmdesc = 0; +#endif + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + #ifdef TEST + fprintf(stderr, "ShmRegisterFbFuncs: Registering shmFuncs as fbFuncs.\n"); + #endif + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + xfree(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + nxagentShmTrap = 0; + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + { + nxagentShmTrap = 1; + return; + } + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + nxagentShmTrap = 1; + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); + nxagentShmTrap = 1; +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + int length; + char *newdata; + extern int nxagentImageLength(int, int, int, int, int); + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Called with drawable at [%p] GC at [%p] data at [%p].\n", + (void *) dst, (void *) pGC, (void *) data); + #endif + + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + + /* + * We updated the internal framebuffer, + * now we want to go on the real X. + */ + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Realizing the PutImage with depth [%d] " + " format [%d] w [%d] h [%d] sx [%d] sy [%d] sw [%d] " + " sh [%d] dx [%d].\n", depth, format, w, h, + sx, sy, sw, sh, dx); + #endif + + length = nxagentImageLength(sw, sh, format, 0, depth); + + if ((newdata = xalloc(length)) != NULL) + { + fbGetImage((DrawablePtr) pPixmap, sx, sy, sw, sh, format, AllPlanes, newdata); + (*pGC->ops->PutImage)(dst, pGC, depth, dx, dy, sw, sh, 0, format, newdata); + + xfree(newdata); + } + else + { + #ifdef WARNING + fprintf(stderr, "fbShmPutImage: WARNING! Data allocation failed.\n"); + #endif + } + + FreeScratchPixmapHeader(pPixmap); + } + else + { + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Calling miShmPutImage().\n"); + #endif + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); + } +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(register ClientPtr client) +{ + int j, result = 0, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != client->noClientException) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + + if (client->swapped) { + register int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static int +ProcPanoramiXShmCreatePixmap(client) + register ClientPtr client; +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + PanoramiXRes *newPix; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = (client->noClientException); + + FOR_NSCREENS(j) { + pScreen = screenInfo.screens[j]; + + pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + xfree(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Format [%d] srcX [%d] srcY [%d], " + "totalWidth [%d] totalHeight [%d]\n", stuff->format, stuff->srcX, + stuff->srcY, stuff->totalWidth, stuff->totalHeight); + #endif + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Calling (*shmFuncs[pDraw->pScreen->myNum]->PutImage)().\n"); + #endif + + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + stuff->offset); + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else + { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + nxagentShmPixmapTrap = 1; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, width, height, depth); + + if (!pPixmap) + { + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + #ifdef TEST + fprintf(stderr,"fbShmCreatePixmap: Width [%d] Height [%d] Depth [%d]\n", width, height, depth); + #endif + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) + { + #ifdef WARNING + fprintf(stderr,"fbShmCreatePixmap: Return Null Pixmap.\n"); + #endif + + (*pScreen->DestroyPixmap)(pPixmap); + + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + nxagentShmPixmapTrap = 0; + + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return(client->noClientException); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + { + result = ProcPanoramiXShmPutImage(client); + + nxagentShmTrap = 0; + + return result; + } +#endif + + result = ProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Returning from ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + + result = SProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Returning from SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXshm.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c.XF86.original new file mode 100644 index 000000000..3ba9ad2c1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c.XF86.original @@ -0,0 +1,1257 @@ +/* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.36 2002/04/03 19:51:11 herrb Exp $ */ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#include +#ifndef Lynx +#include +#include +#else +#include +#include +#endif +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include "shmstr.h" +#include "Xfuncproto.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( +#if NeedFunctionPrototypes + pointer /* value */, + XID /* shmseg */ +#endif + ); +static void ShmResetProc( +#if NeedFunctionPrototypes + ExtensionEntry * /* extEntry */ +#endif + ); +static void SShmCompletionEvent( +#if NeedFunctionPrototypes + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ +#endif + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +#ifdef PIXPRIV +static int shmPixmapPrivate; +#endif +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall() +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + /* Clean up */ + if (shmid != -1) + { + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} +#endif + +void +ShmExtensionInit() +{ + ExtensionEntry *extEntry; + int i; + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + sharedPixmaps = xTrue; + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + shmFuncs[i] = &miFuncs; + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; + if (sharedPixmaps) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } +#ifdef PIXPRIV + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } +#endif + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs(pScreen, funcs) + ScreenPtr pScreen; + ShmFuncsPtr funcs; +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat(pScreen, format) + ScreenPtr pScreen; + int format; +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; +#ifdef PIXPRIV + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; +#else + char *base = (char *) pPixmap->devPrivate.ptr; + + if (base != (pointer) (pPixmap + 1)) + { + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) + { + if (shmdesc->addr <= base && base <= shmdesc->addr + shmdesc->size) + break; + } + } + else + shmdesc = 0; +#endif + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + xfree(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + return; + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + FreeScratchPixmapHeader(pPixmap); + } + else + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(register ClientPtr client) +{ + int j, result = 0, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != client->noClientException) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + + if (client->swapped) { + register int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static int +ProcPanoramiXShmCreatePixmap(client) + register ClientPtr client; +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + PanoramiXRes *newPix; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = (client->noClientException); + + FOR_NSCREENS(j) { + pScreen = screenInfo.screens[j]; + + pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + xfree(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || + ((stuff->format != ZPixmap) && + (stuff->srcX < screenInfo.bitmapScanlinePad) && + ((stuff->format == XYBitmap) || + ((stuff->srcY == 0) && + (stuff->srcHeight == stuff->totalHeight))))) && + ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, + stuff->dstX, stuff->dstY, + stuff->totalWidth, stuff->srcHeight, + stuff->srcX, stuff->format, + shmdesc->addr + stuff->offset + + (stuff->srcY * length)); + else + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + stuff->offset); + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else + { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); + if (!pPixmap) + return NullPixmap; + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { + (*pScreen->DestroyPixmap)(pPixmap); + return NullPixmap; + } + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return(client->noClientException); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmPutImage(client); +#endif + return ProcShmPutImage(client); + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + return SProcShmPutImage(client); + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c new file mode 100644 index 000000000..16328f9ab --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c @@ -0,0 +1,4179 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXwindow.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/**************************************************************** +* * +* 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. * +* * +*****************************************************************/ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "selection.h" +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif +#include "dixevents.h" +#include "globals.h" + +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif + +#include "Screen.h" +#include "Options.h" +#include "Atoms.h" +#include "Clipboard.h" +#include "Splash.h" +#include "Rootless.h" +#include "Composite.h" +#include "Drawable.h" +#include "Colormap.h" + +#if defined(NEED_SCREEN_REGIONS) +#define REGION_PTR(pScreen,pWin) \ + register ScreenPtr pScreen = pWin->drawable.pScreen; +#else +#define REGION_PTR(pScreen,pWin) /* nothing */ +#endif + +extern Bool nxagentWMIsRunning; +extern Bool nxagentScreenTrap; + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +int screenIsSaved = SCREEN_SAVER_OFF; + +ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#if 0 +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +#endif + +static Bool TileScreenSaver( +#if NeedFunctionPrototypes + int /*i*/, + int /*kind*/ +#endif +); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int numSaveUndersViewable = 0; +int deltaSaveUndersViewable = 0; + +WindowPtr nxagentRootTileWindow; + +/* + * This block used the DEBUG symbol. + */ + +#ifdef WINDOW_TREE_DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(p1, indent) + WindowPtr p1; + int indent; +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; idrawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; iclipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +int +TraverseTree(pWin, func, data) + register WindowPtr pWin; + VisitWindowProcPtr func; + pointer data; +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +int +WalkTree(pScreen, func, data) + ScreenPtr pScreen; + VisitWindowProcPtr func; + pointer data; +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +Bool enableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +#if NeedFunctionPrototypes +SetWindowToDefaults(register WindowPtr pWin) +#else +SetWindowToDefaults(pWin) + register WindowPtr pWin; +#endif +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +} + +void nxagentClearSplash(WindowPtr pW) +{ + int w, h; + ScreenPtr pScreen; + + w = pW->drawable.width; + h = pW->drawable.height; + + pScreen = pW->drawable.pScreen; + + if (pW->backgroundState == BackgroundPixmap) + { + (*pScreen->DestroyPixmap)(pW->background.pixmap); + } + + pW->backgroundState = BackgroundPixel; + pW->background.pixel = nxagentLogoBlack; + + (*pScreen->ChangeWindowAttributes)(pW, CWBackPixmap|CWBackPixel); +} + +static void +#if NeedFunctionPrototypes +MakeRootTile(WindowPtr pWin) +#else +MakeRootTile(pWin) + WindowPtr pWin; +#endif +{ + nxagentRootTileWindow = pWin; +} + +WindowPtr +AllocateWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + { + pScreen -> backingStoreSupport = NotUseful; + } + + if (enableBackingStore) + { + pScreen -> backingStoreSupport = Always; + } + + pScreen->saveUnderSupport = False; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +void +InitRootWindow(pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen; + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Called for window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (nxagentOption(Rootless)) + { + #ifdef TEST + fprintf(stderr, "InitRootWindow: Assigned agent root to window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + nxagentRootlessWindow = pWin; + } + + pScreen = pWin->drawable.pScreen; + + /* + * A root window is created for each screen by main + * and the pointer is saved in WindowTable as in the + * following snippet: + * + * for (i = 0; i < screenInfo.numScreens; i++) + * InitRootWindow(WindowTable[i]); + * + * Our root window on the real display was already + * created at the time the screen was opened, so it + * is unclear how this window (or the other window, + * if you prefer) fits in the big picture. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Going to create window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Created window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + + #ifdef NXAGENT_SPLASH + /* We SHOULD check for an error value here XXX */ + pWin -> background.pixel = pScreen -> blackPixel; + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixel|CWBorderPixel|CWCursor|CWBackingStore); + #else + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + #endif + + MakeRootTile(pWin); + + /* + * Map both the root and the default agent window. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Mapping default windows.\n"); + #endif + + nxagentInitAtoms(pWin); + + nxagentInitClipboard(pWin); + + nxagentMapDefaultWindows(); + + nxagentRedirectDefaultWindows(); + + #ifdef NXAGENT_ARTSD + { + char artsd_port[10]; + int nPort; + extern void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port); + nPort = atoi(display) + 7000; + sprintf(artsd_port,"%d", nPort); + nxagentPropagateArtsdProperties(pScreen, artsd_port); + } + #endif +} + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(pWin, Rgn, x, y, w, h) + register WindowPtr pWin; + RegionPtr Rgn; + register int x, y; + int w, h; +{ + REGION_PTR(pScreen, pWin) + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +WindowPtr +RealChildHead(pWin) + register WindowPtr pWin; +{ + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +WindowPtr +CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist, + depth, client, visual, error) + Window wid; + register WindowPtr pParent; + int x,y; + unsigned int w, h, bw; + unsigned int class; + register Mask vmask; + XID *vlist; + int depth; + ClientPtr client; + VisualID visual; + int *error; +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (client->trustLevel != XSecurityClientTrusted) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_INIT(pScreen, &pWin->clipList, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderClip, NullBox, 1); + REGION_INIT(pScreen, &pWin->winSize, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderSize, NullBox, 1); + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + return pWin; +} + +static void +#if NeedFunctionPrototypes +FreeWindowResources(register WindowPtr pWin) +#else +FreeWindowResources(pWin) + register WindowPtr pWin; +#endif +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +#if NeedFunctionPrototypes +CrushTree(WindowPtr pWin) +#else +CrushTree(pWin) + WindowPtr pWin; +#endif +{ + register WindowPtr pChild, pSib, pParent; + UnrealizeWindowProcPtr UnrealizeWindow; + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +/*ARGSUSED*/ +int +DeleteWindow(value, wid) + pointer value; + XID wid; + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + xfree(pWin); + + if (pWin -> optional && + pWin -> optional -> colormap && + pWin -> parent) + { + nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen); + } + + return Success; +} + +/*ARGSUSED*/ +void +DestroySubwindows(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +int +ChangeWindowAttributes(pWin, vmask, vlist, client) + register WindowPtr pWin; + Mask vmask; + XID *vlist; + ClientPtr client; +{ + register Mask index2; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index2 = (Mask) lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows */ + if (client->trustLevel == XSecurityClientTrusted) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XCSECURITY + } + else + { /* didn't change the background to None, so don't tell ddx */ + index2 = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index2 = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + + #ifdef TEST + fprintf(stderr, "ChangeWindowAttributes: Changed backing store value to %d for window at %p.\n", + val, (void*)pWin); + #endif + + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == (CARD32)~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + /* + * TODO: Some applications like java bean shell + * don' t work if they cannot monitor the root + * window for Structure Redirect events. However + * this doesn't seem to be the best solution, since + * also an X server with a window manager running, + * doesn't allow to monitor for those events, but + * the java bean shell works flawlessy on this + * server. + * + * if (nxagentCheckIllegalRootMonitoring(pWin, (Mask)*pVlist)) + * { + * return BadAccess; + * } + */ + + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if ( win_owner && win_owner->appgroup && + !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index2; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_INIT(pScreen, &exposed, NullBox, 0); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(pWin, client, wa) + register WindowPtr pWin; + ClientPtr client; + xGetWindowAttributesReply *wa; +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +WindowPtr +MoveWindowInStack(pWin, pNextSib) + register WindowPtr pWin, pNextSib; +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + WindowPtr pOldNextSib = pWin->nextSib; + + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + if(pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); + } + + return( pFirstChange ); +} + +RegionPtr +CreateUnclippedWinSize (pWin) + register WindowPtr pWin; +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +void +SetWinSize (pWin) + register WindowPtr pWin; +{ + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +void +SetBorderSize (pWin) + register WindowPtr pWin; +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +void +GravityTranslate (x, y, oldx, oldy, dw, dh, gravity, destx, desty) + register int x, y; /* new window position */ + int oldx, oldy; /* old window position */ + int dw, dh; + unsigned gravity; + register int *destx, *desty; /* position relative to gravity */ +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +void +ResizeChildrenWinSize(pWin, dx, dy, dw, dh) + register WindowPtr pWin; + int dx, dy, dw, dh; +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + + /* + * Don't force X to move children. It will position them + * according with gravity. + * + * (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + */ + + /* + * Update pSib privates, as this window is moved by X. + */ + + nxagentAddConfiguredWindow(pSib, CW_Update); + + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + + (*pScreen->PositionWindow)(pChild, pChild->drawable.x, + pChild->drawable.y); + + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +#if NeedFunctionPrototypes +IsSiblingAboveMe( + register WindowPtr pMe, + register WindowPtr pSib) +#else +IsSiblingAboveMe(pMe, pSib) + register WindowPtr pMe, pSib; +#endif +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +#if NeedFunctionPrototypes +WindowExtents( + register WindowPtr pWin, + register BoxPtr pBox) +#else +WindowExtents(pWin, pBox) + register WindowPtr pWin; + register BoxPtr pBox; +#endif +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +#if NeedFunctionPrototypes +MakeBoundingRegion ( + register WindowPtr pWin, + BoxPtr pBox) +#else +MakeBoundingRegion (pWin, pBox) + register WindowPtr pWin; + BoxPtr pBox; +#endif +{ + RegionPtr pRgn; + REGION_PTR(pScreen, pWin) + + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +#if NeedFunctionPrototypes +ShapeOverlap ( + WindowPtr pWin, + BoxPtr pWinBox, + WindowPtr pSib, + BoxPtr pSibBox) +#else +ShapeOverlap (pWin, pWinBox, pSib, pSibBox) + WindowPtr pWin, pSib; + BoxPtr pWinBox, pSibBox; +#endif +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +#if NeedFunctionPrototypes +AnyWindowOverlapsMe( + WindowPtr pWin, + WindowPtr pHead, + register BoxPtr box) +#else +AnyWindowOverlapsMe(pWin, pHead, box) + WindowPtr pWin, pHead; + register BoxPtr box; +#endif +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +#if NeedFunctionPrototypes +IOverlapAnyWindow( + WindowPtr pWin, + register BoxPtr box) +#else +IOverlapAnyWindow(pWin, box) + WindowPtr pWin; + register BoxPtr box; +#endif +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +#if NeedFunctionPrototypes +WhereDoIGoInTheStack( + register WindowPtr pWin, + register WindowPtr pSib, + short x, + short y, + unsigned short w, + unsigned short h, + int smode) +#else +WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode) + register WindowPtr pWin, pSib; + short x, y; + unsigned short w, h; + int smode; +#endif +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +#if NeedFunctionPrototypes +ReflectStackChange( + register WindowPtr pWin, + register WindowPtr pSib, + VTKind kind) +#else +ReflectStackChange(pWin, pSib, kind) + register WindowPtr pWin, pSib; + VTKind kind; +#endif +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + WindowPtr pParent; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!(pParent = pWin->parent)) + return ; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(pWin, mask, vlist, client) + register WindowPtr pWin; + register Mask mask; + XID *vlist; + ClientPtr client; +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid = 0; + Mask index2, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index2 = (Mask)lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + + fprintf(stderr, "ConfigureWindow: pWin [%p] mask [%lu] client [%p]\n", + pWin, mask, client); + + fprintf(stderr, "ConfigureWindow: x [%d] y [%d] w [%d] h [%d] CWStackMode [%d] " + "smode [%d] pSib [%p]\n", + x, y, w, h, (mask & CWStackMode) ? 1 : 0, smode, pSib); + } + #endif + + if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin) && + pWin -> overrideRedirect == 0 && + nxagentScreenTrap == 0) + { + nxagentConfigureRootlessWindow(pWin, x, y, w, h, bw, pSib, smode, mask); + + return Success; + } + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureRequest.x += panoramiXdataPtr[0].x; + event.u.configureRequest.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { + if (pWin->nextSib != pSib) + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureNotify.x += panoramiXdataPtr[0].x; + event.u.configureNotify.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + + nxagentFlushConfigureWindow(); + + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(pParent, direction, client) + WindowPtr pParent; + int direction; + ClientPtr client; +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + #ifdef TEST + fprintf(stderr, "CirculateWindow: pParent [%p] direction [%d] client [%p]\n", + pParent, direction, client); + #endif + + /* + * if (nxagentOption(Rootless) && nxagentWMIsRunning && + * nxagentWindowTopLevel(pWin) && pWin -> overrideRedirect == 0) + * { + * nxagentCirculateRootlessWindows(direction); + * return Success; + * } + */ + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +#if NeedFunctionPrototypes +CompareWIDs( + WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +#else +CompareWIDs(pWin, value) + WindowPtr pWin; + pointer value; /* must conform to VisitWindowProcPtr */ +#endif +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(pWin, pParent, x, y, client) + register WindowPtr pWin, pParent; + int x,y; + ClientPtr client; +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pParent->parent) { + event.u.reparent.x += panoramiXdataPtr[0].x; + event.u.reparent.y += panoramiXdataPtr[0].y; + } +#endif + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + + if (pWin->parent == WindowTable[0]) + { + nxagentSetTopLevelEventMask(pWin); + } + + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +#if NeedFunctionPrototypes +RealizeTree(WindowPtr pWin) +#else +RealizeTree(pWin) + WindowPtr pWin; +#endif +{ + register WindowPtr pChild; + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +int +MapWindow(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "MapWindow: pWin [%p] client [%p]\n", pWin, client); + } + #endif + + if (pWin->mapped) + return(Success); + +#ifdef XCSECURITY + /* don't let an untrusted client map a child-of-trusted-window, InputOnly + * window; too easy to steal device input + */ + if ( (client->trustLevel != XSecurityClientTrusted) && + (pWin->drawable.class == InputOnly) && + (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) ) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_INIT(pScreen, &temp, NullBox, 0); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + nxagentFlushConfigureWindow(); + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(pParent, client) + register WindowPtr pParent; + ClientPtr client; +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +#if NeedFunctionPrototypes +UnrealizeTree( + WindowPtr pWin, + Bool fromConfigure) +#else +UnrealizeTree(pWin, fromConfigure) + WindowPtr pWin; + Bool fromConfigure; +#endif +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { + PanoramiXRes *win; + win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, + XRT_WINDOW); + if(win) + win->u.win.visibility = VisibilityNotViewable; + } +#endif + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +int +UnmapWindow(pWin, fromConfigure) + register WindowPtr pWin; + Bool fromConfigure; +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "UnmapWindow: pWin [%p] fromConfigure [%d]\n", pWin, + fromConfigure); + } + #endif + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(pWin) + register WindowPtr pWin; +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin = NULL; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; jnumSaved; j++) + { + pWin = (WindowPtr)client->saveSet[j]; + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (pointer *)NULL; +} + +Bool +VisibleBoundingBoxFromPoint(pWin, x, y, box) + register WindowPtr pWin; + int x, y; /* in root */ + BoxPtr box; /* "return" value */ +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +Bool +PointInWindowIsVisible(pWin, x, y) + register WindowPtr pWin; + int x, y; /* in root */ +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box)) + return(TRUE); + return(FALSE); +} + + +RegionPtr +NotClippedByChildren(pWin) + register WindowPtr pWin; +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + +void +SendVisibilityNotify(pWin) + WindowPtr pWin; +{ + xEvent event; + unsigned int visibility = pWin->visibility; + +#ifdef PANORAMIX + /* This is not quite correct yet, but it's close */ + if(!noPanoramiXExtension) { + PanoramiXRes *win; + WindowPtr pWin2; + int i, Scrnum; + + Scrnum = pWin->drawable.pScreen->myNum; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); + + if(!win || (win->u.win.visibility == visibility)) + return; + + switch(visibility) { + case VisibilityUnobscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility == VisibilityPartiallyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + case VisibilityPartiallyObscured: + if(Scrnum) { + pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); + if (pWin2) pWin = pWin2; + } + break; + case VisibilityFullyObscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility != VisibilityFullyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + } + + win->u.win.visibility = visibility; + } +#endif + + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +static void DrawLogo( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); +#endif + +void +SaveScreens(on, mode) + int on; + int mode; +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if (nxagentOption(Timeout) != 0) + { + #ifdef TEST + fprintf(stderr, "SaveScreens: An external screen-saver handler is installed. " + "Ignoring it to let the auto-disconnect feature work.\n"); + #endif + } + else + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + /* + * Call the DDX saver in case it wants to do something + * at cycle time + */ + else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + type); + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; +} + +static Bool +#if NeedFunctionPrototypes +TileScreenSaver(int i, int kind) +#else +TileScreenSaver(i, kind) + int i; + int kind; +#endif +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID = 0; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; jwidth + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +WindowPtr +FindWindowWithOptional (w) + register WindowPtr w; +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +void +CheckWindowOptionalNeed (w) + register WindowPtr w; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +Bool +MakeWindowOptional (pWin) + register WindowPtr pWin; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (pWin) + register WindowPtr pWin; +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + /* + * TOG changed this code to: + * + * if (pWin->cursorIsNone == FALSE) + * FreeCursor (pWin->optional->cursor, (Cursor)0); + * pWin->cursorIsNone = TRUE; + * + * This is blatently wrong; windows without optionals can have + * two different cursor values, either None or sharing their + * parents cursor. This difference is controlled by the + * cursorIsNone value; when TRUE, the window has no cursor, + * when false, it shares its cursor with its parent; TOG + * made it impossible for a window to have a cursor without + * an optional record. + */ + if (pWin->optional->cursor) + { + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = FALSE; + } + else + pWin->cursorIsNone = TRUE; +/* FIXME + There is an error when disposing ClientResources on Agent exit + this xfree is not valid in some window at exit +*/ + + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +#if NeedFunctionPrototypes +DrawLogo(WindowPtr pWin) +#else +DrawLogo(pWin) + WindowPtr pWin; +#endif +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.NX.original new file mode 100644 index 000000000..16328f9ab --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.NX.original @@ -0,0 +1,4179 @@ +#ifdef NXAGENT_UPGRADE + +#include "X/NXwindow.c" + +#else + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/**************************************************************** +* * +* 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. * +* * +*****************************************************************/ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "selection.h" +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif +#include "dixevents.h" +#include "globals.h" + +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif + +#include "Screen.h" +#include "Options.h" +#include "Atoms.h" +#include "Clipboard.h" +#include "Splash.h" +#include "Rootless.h" +#include "Composite.h" +#include "Drawable.h" +#include "Colormap.h" + +#if defined(NEED_SCREEN_REGIONS) +#define REGION_PTR(pScreen,pWin) \ + register ScreenPtr pScreen = pWin->drawable.pScreen; +#else +#define REGION_PTR(pScreen,pWin) /* nothing */ +#endif + +extern Bool nxagentWMIsRunning; +extern Bool nxagentScreenTrap; + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +int screenIsSaved = SCREEN_SAVER_OFF; + +ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#if 0 +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +#endif + +static Bool TileScreenSaver( +#if NeedFunctionPrototypes + int /*i*/, + int /*kind*/ +#endif +); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int numSaveUndersViewable = 0; +int deltaSaveUndersViewable = 0; + +WindowPtr nxagentRootTileWindow; + +/* + * This block used the DEBUG symbol. + */ + +#ifdef WINDOW_TREE_DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(p1, indent) + WindowPtr p1; + int indent; +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; idrawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; iclipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +int +TraverseTree(pWin, func, data) + register WindowPtr pWin; + VisitWindowProcPtr func; + pointer data; +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +int +WalkTree(pScreen, func, data) + ScreenPtr pScreen; + VisitWindowProcPtr func; + pointer data; +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +Bool enableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +#if NeedFunctionPrototypes +SetWindowToDefaults(register WindowPtr pWin) +#else +SetWindowToDefaults(pWin) + register WindowPtr pWin; +#endif +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +} + +void nxagentClearSplash(WindowPtr pW) +{ + int w, h; + ScreenPtr pScreen; + + w = pW->drawable.width; + h = pW->drawable.height; + + pScreen = pW->drawable.pScreen; + + if (pW->backgroundState == BackgroundPixmap) + { + (*pScreen->DestroyPixmap)(pW->background.pixmap); + } + + pW->backgroundState = BackgroundPixel; + pW->background.pixel = nxagentLogoBlack; + + (*pScreen->ChangeWindowAttributes)(pW, CWBackPixmap|CWBackPixel); +} + +static void +#if NeedFunctionPrototypes +MakeRootTile(WindowPtr pWin) +#else +MakeRootTile(pWin) + WindowPtr pWin; +#endif +{ + nxagentRootTileWindow = pWin; +} + +WindowPtr +AllocateWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + { + pScreen -> backingStoreSupport = NotUseful; + } + + if (enableBackingStore) + { + pScreen -> backingStoreSupport = Always; + } + + pScreen->saveUnderSupport = False; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +void +InitRootWindow(pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen; + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Called for window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (nxagentOption(Rootless)) + { + #ifdef TEST + fprintf(stderr, "InitRootWindow: Assigned agent root to window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + nxagentRootlessWindow = pWin; + } + + pScreen = pWin->drawable.pScreen; + + /* + * A root window is created for each screen by main + * and the pointer is saved in WindowTable as in the + * following snippet: + * + * for (i = 0; i < screenInfo.numScreens; i++) + * InitRootWindow(WindowTable[i]); + * + * Our root window on the real display was already + * created at the time the screen was opened, so it + * is unclear how this window (or the other window, + * if you prefer) fits in the big picture. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Going to create window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Created window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + + #ifdef NXAGENT_SPLASH + /* We SHOULD check for an error value here XXX */ + pWin -> background.pixel = pScreen -> blackPixel; + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixel|CWBorderPixel|CWCursor|CWBackingStore); + #else + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + #endif + + MakeRootTile(pWin); + + /* + * Map both the root and the default agent window. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Mapping default windows.\n"); + #endif + + nxagentInitAtoms(pWin); + + nxagentInitClipboard(pWin); + + nxagentMapDefaultWindows(); + + nxagentRedirectDefaultWindows(); + + #ifdef NXAGENT_ARTSD + { + char artsd_port[10]; + int nPort; + extern void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port); + nPort = atoi(display) + 7000; + sprintf(artsd_port,"%d", nPort); + nxagentPropagateArtsdProperties(pScreen, artsd_port); + } + #endif +} + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(pWin, Rgn, x, y, w, h) + register WindowPtr pWin; + RegionPtr Rgn; + register int x, y; + int w, h; +{ + REGION_PTR(pScreen, pWin) + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +WindowPtr +RealChildHead(pWin) + register WindowPtr pWin; +{ + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +WindowPtr +CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist, + depth, client, visual, error) + Window wid; + register WindowPtr pParent; + int x,y; + unsigned int w, h, bw; + unsigned int class; + register Mask vmask; + XID *vlist; + int depth; + ClientPtr client; + VisualID visual; + int *error; +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (client->trustLevel != XSecurityClientTrusted) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_INIT(pScreen, &pWin->clipList, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderClip, NullBox, 1); + REGION_INIT(pScreen, &pWin->winSize, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderSize, NullBox, 1); + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + return pWin; +} + +static void +#if NeedFunctionPrototypes +FreeWindowResources(register WindowPtr pWin) +#else +FreeWindowResources(pWin) + register WindowPtr pWin; +#endif +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +#if NeedFunctionPrototypes +CrushTree(WindowPtr pWin) +#else +CrushTree(pWin) + WindowPtr pWin; +#endif +{ + register WindowPtr pChild, pSib, pParent; + UnrealizeWindowProcPtr UnrealizeWindow; + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +/*ARGSUSED*/ +int +DeleteWindow(value, wid) + pointer value; + XID wid; + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + xfree(pWin); + + if (pWin -> optional && + pWin -> optional -> colormap && + pWin -> parent) + { + nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen); + } + + return Success; +} + +/*ARGSUSED*/ +void +DestroySubwindows(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +int +ChangeWindowAttributes(pWin, vmask, vlist, client) + register WindowPtr pWin; + Mask vmask; + XID *vlist; + ClientPtr client; +{ + register Mask index2; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index2 = (Mask) lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows */ + if (client->trustLevel == XSecurityClientTrusted) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XCSECURITY + } + else + { /* didn't change the background to None, so don't tell ddx */ + index2 = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index2 = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + + #ifdef TEST + fprintf(stderr, "ChangeWindowAttributes: Changed backing store value to %d for window at %p.\n", + val, (void*)pWin); + #endif + + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == (CARD32)~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + /* + * TODO: Some applications like java bean shell + * don' t work if they cannot monitor the root + * window for Structure Redirect events. However + * this doesn't seem to be the best solution, since + * also an X server with a window manager running, + * doesn't allow to monitor for those events, but + * the java bean shell works flawlessy on this + * server. + * + * if (nxagentCheckIllegalRootMonitoring(pWin, (Mask)*pVlist)) + * { + * return BadAccess; + * } + */ + + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if ( win_owner && win_owner->appgroup && + !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index2; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_INIT(pScreen, &exposed, NullBox, 0); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(pWin, client, wa) + register WindowPtr pWin; + ClientPtr client; + xGetWindowAttributesReply *wa; +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +WindowPtr +MoveWindowInStack(pWin, pNextSib) + register WindowPtr pWin, pNextSib; +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + WindowPtr pOldNextSib = pWin->nextSib; + + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + if(pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); + } + + return( pFirstChange ); +} + +RegionPtr +CreateUnclippedWinSize (pWin) + register WindowPtr pWin; +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +void +SetWinSize (pWin) + register WindowPtr pWin; +{ + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +void +SetBorderSize (pWin) + register WindowPtr pWin; +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +void +GravityTranslate (x, y, oldx, oldy, dw, dh, gravity, destx, desty) + register int x, y; /* new window position */ + int oldx, oldy; /* old window position */ + int dw, dh; + unsigned gravity; + register int *destx, *desty; /* position relative to gravity */ +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +void +ResizeChildrenWinSize(pWin, dx, dy, dw, dh) + register WindowPtr pWin; + int dx, dy, dw, dh; +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + + /* + * Don't force X to move children. It will position them + * according with gravity. + * + * (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + */ + + /* + * Update pSib privates, as this window is moved by X. + */ + + nxagentAddConfiguredWindow(pSib, CW_Update); + + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + + (*pScreen->PositionWindow)(pChild, pChild->drawable.x, + pChild->drawable.y); + + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +#if NeedFunctionPrototypes +IsSiblingAboveMe( + register WindowPtr pMe, + register WindowPtr pSib) +#else +IsSiblingAboveMe(pMe, pSib) + register WindowPtr pMe, pSib; +#endif +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +#if NeedFunctionPrototypes +WindowExtents( + register WindowPtr pWin, + register BoxPtr pBox) +#else +WindowExtents(pWin, pBox) + register WindowPtr pWin; + register BoxPtr pBox; +#endif +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +#if NeedFunctionPrototypes +MakeBoundingRegion ( + register WindowPtr pWin, + BoxPtr pBox) +#else +MakeBoundingRegion (pWin, pBox) + register WindowPtr pWin; + BoxPtr pBox; +#endif +{ + RegionPtr pRgn; + REGION_PTR(pScreen, pWin) + + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +#if NeedFunctionPrototypes +ShapeOverlap ( + WindowPtr pWin, + BoxPtr pWinBox, + WindowPtr pSib, + BoxPtr pSibBox) +#else +ShapeOverlap (pWin, pWinBox, pSib, pSibBox) + WindowPtr pWin, pSib; + BoxPtr pWinBox, pSibBox; +#endif +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +#if NeedFunctionPrototypes +AnyWindowOverlapsMe( + WindowPtr pWin, + WindowPtr pHead, + register BoxPtr box) +#else +AnyWindowOverlapsMe(pWin, pHead, box) + WindowPtr pWin, pHead; + register BoxPtr box; +#endif +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +#if NeedFunctionPrototypes +IOverlapAnyWindow( + WindowPtr pWin, + register BoxPtr box) +#else +IOverlapAnyWindow(pWin, box) + WindowPtr pWin; + register BoxPtr box; +#endif +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +#if NeedFunctionPrototypes +WhereDoIGoInTheStack( + register WindowPtr pWin, + register WindowPtr pSib, + short x, + short y, + unsigned short w, + unsigned short h, + int smode) +#else +WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode) + register WindowPtr pWin, pSib; + short x, y; + unsigned short w, h; + int smode; +#endif +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +#if NeedFunctionPrototypes +ReflectStackChange( + register WindowPtr pWin, + register WindowPtr pSib, + VTKind kind) +#else +ReflectStackChange(pWin, pSib, kind) + register WindowPtr pWin, pSib; + VTKind kind; +#endif +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + WindowPtr pParent; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!(pParent = pWin->parent)) + return ; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(pWin, mask, vlist, client) + register WindowPtr pWin; + register Mask mask; + XID *vlist; + ClientPtr client; +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid = 0; + Mask index2, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index2 = (Mask)lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + + fprintf(stderr, "ConfigureWindow: pWin [%p] mask [%lu] client [%p]\n", + pWin, mask, client); + + fprintf(stderr, "ConfigureWindow: x [%d] y [%d] w [%d] h [%d] CWStackMode [%d] " + "smode [%d] pSib [%p]\n", + x, y, w, h, (mask & CWStackMode) ? 1 : 0, smode, pSib); + } + #endif + + if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin) && + pWin -> overrideRedirect == 0 && + nxagentScreenTrap == 0) + { + nxagentConfigureRootlessWindow(pWin, x, y, w, h, bw, pSib, smode, mask); + + return Success; + } + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureRequest.x += panoramiXdataPtr[0].x; + event.u.configureRequest.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { + if (pWin->nextSib != pSib) + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureNotify.x += panoramiXdataPtr[0].x; + event.u.configureNotify.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + + nxagentFlushConfigureWindow(); + + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(pParent, direction, client) + WindowPtr pParent; + int direction; + ClientPtr client; +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + #ifdef TEST + fprintf(stderr, "CirculateWindow: pParent [%p] direction [%d] client [%p]\n", + pParent, direction, client); + #endif + + /* + * if (nxagentOption(Rootless) && nxagentWMIsRunning && + * nxagentWindowTopLevel(pWin) && pWin -> overrideRedirect == 0) + * { + * nxagentCirculateRootlessWindows(direction); + * return Success; + * } + */ + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +#if NeedFunctionPrototypes +CompareWIDs( + WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +#else +CompareWIDs(pWin, value) + WindowPtr pWin; + pointer value; /* must conform to VisitWindowProcPtr */ +#endif +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(pWin, pParent, x, y, client) + register WindowPtr pWin, pParent; + int x,y; + ClientPtr client; +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pParent->parent) { + event.u.reparent.x += panoramiXdataPtr[0].x; + event.u.reparent.y += panoramiXdataPtr[0].y; + } +#endif + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + + if (pWin->parent == WindowTable[0]) + { + nxagentSetTopLevelEventMask(pWin); + } + + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +#if NeedFunctionPrototypes +RealizeTree(WindowPtr pWin) +#else +RealizeTree(pWin) + WindowPtr pWin; +#endif +{ + register WindowPtr pChild; + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +int +MapWindow(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "MapWindow: pWin [%p] client [%p]\n", pWin, client); + } + #endif + + if (pWin->mapped) + return(Success); + +#ifdef XCSECURITY + /* don't let an untrusted client map a child-of-trusted-window, InputOnly + * window; too easy to steal device input + */ + if ( (client->trustLevel != XSecurityClientTrusted) && + (pWin->drawable.class == InputOnly) && + (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) ) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_INIT(pScreen, &temp, NullBox, 0); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + nxagentFlushConfigureWindow(); + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(pParent, client) + register WindowPtr pParent; + ClientPtr client; +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +#if NeedFunctionPrototypes +UnrealizeTree( + WindowPtr pWin, + Bool fromConfigure) +#else +UnrealizeTree(pWin, fromConfigure) + WindowPtr pWin; + Bool fromConfigure; +#endif +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { + PanoramiXRes *win; + win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, + XRT_WINDOW); + if(win) + win->u.win.visibility = VisibilityNotViewable; + } +#endif + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +int +UnmapWindow(pWin, fromConfigure) + register WindowPtr pWin; + Bool fromConfigure; +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "UnmapWindow: pWin [%p] fromConfigure [%d]\n", pWin, + fromConfigure); + } + #endif + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(pWin) + register WindowPtr pWin; +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin = NULL; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; jnumSaved; j++) + { + pWin = (WindowPtr)client->saveSet[j]; + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (pointer *)NULL; +} + +Bool +VisibleBoundingBoxFromPoint(pWin, x, y, box) + register WindowPtr pWin; + int x, y; /* in root */ + BoxPtr box; /* "return" value */ +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +Bool +PointInWindowIsVisible(pWin, x, y) + register WindowPtr pWin; + int x, y; /* in root */ +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box)) + return(TRUE); + return(FALSE); +} + + +RegionPtr +NotClippedByChildren(pWin) + register WindowPtr pWin; +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + +void +SendVisibilityNotify(pWin) + WindowPtr pWin; +{ + xEvent event; + unsigned int visibility = pWin->visibility; + +#ifdef PANORAMIX + /* This is not quite correct yet, but it's close */ + if(!noPanoramiXExtension) { + PanoramiXRes *win; + WindowPtr pWin2; + int i, Scrnum; + + Scrnum = pWin->drawable.pScreen->myNum; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); + + if(!win || (win->u.win.visibility == visibility)) + return; + + switch(visibility) { + case VisibilityUnobscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility == VisibilityPartiallyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + case VisibilityPartiallyObscured: + if(Scrnum) { + pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); + if (pWin2) pWin = pWin2; + } + break; + case VisibilityFullyObscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility != VisibilityFullyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + } + + win->u.win.visibility = visibility; + } +#endif + + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +static void DrawLogo( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); +#endif + +void +SaveScreens(on, mode) + int on; + int mode; +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if (nxagentOption(Timeout) != 0) + { + #ifdef TEST + fprintf(stderr, "SaveScreens: An external screen-saver handler is installed. " + "Ignoring it to let the auto-disconnect feature work.\n"); + #endif + } + else + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + /* + * Call the DDX saver in case it wants to do something + * at cycle time + */ + else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + type); + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; +} + +static Bool +#if NeedFunctionPrototypes +TileScreenSaver(int i, int kind) +#else +TileScreenSaver(i, kind) + int i; + int kind; +#endif +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID = 0; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; jwidth + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +WindowPtr +FindWindowWithOptional (w) + register WindowPtr w; +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +void +CheckWindowOptionalNeed (w) + register WindowPtr w; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +Bool +MakeWindowOptional (pWin) + register WindowPtr pWin; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (pWin) + register WindowPtr pWin; +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + /* + * TOG changed this code to: + * + * if (pWin->cursorIsNone == FALSE) + * FreeCursor (pWin->optional->cursor, (Cursor)0); + * pWin->cursorIsNone = TRUE; + * + * This is blatently wrong; windows without optionals can have + * two different cursor values, either None or sharing their + * parents cursor. This difference is controlled by the + * cursorIsNone value; when TRUE, the window has no cursor, + * when false, it shares its cursor with its parent; TOG + * made it impossible for a window to have a cursor without + * an optional record. + */ + if (pWin->optional->cursor) + { + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = FALSE; + } + else + pWin->cursorIsNone = TRUE; +/* FIXME + There is an error when disposing ClientResources on Agent exit + this xfree is not valid in some window at exit +*/ + + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +#if NeedFunctionPrototypes +DrawLogo(WindowPtr pWin) +#else +DrawLogo(pWin) + WindowPtr pWin; +#endif +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.XF86.original new file mode 100644 index 000000000..30c0df032 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.XF86.original @@ -0,0 +1,3947 @@ +/* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) 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. * +* * +*****************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/window.c,v 3.32 2003/01/12 02:44:26 dawes Exp $ */ + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "dixevents.h" +#include "globals.h" + +#ifdef XAPPGROUP +#include "Xagsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif + +#if defined(NEED_SCREEN_REGIONS) +#define REGION_PTR(pScreen,pWin) \ + register ScreenPtr pScreen = pWin->drawable.pScreen; +#else +#define REGION_PTR(pScreen,pWin) /* nothing */ +#endif + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11}; +static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88}; + +int screenIsSaved = SCREEN_SAVER_OFF; + +ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#if 0 +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +#endif + +static Bool TileScreenSaver( +#if NeedFunctionPrototypes + int /*i*/, + int /*kind*/ +#endif +); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +int numSaveUndersViewable = 0; +int deltaSaveUndersViewable = 0; + +#ifdef DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(p1, indent) + WindowPtr p1; + int indent; +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; idrawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; iclipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +int +TraverseTree(pWin, func, data) + register WindowPtr pWin; + VisitWindowProcPtr func; + pointer data; +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +int +WalkTree(pScreen, func, data) + ScreenPtr pScreen; + VisitWindowProcPtr func; + pointer data; +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +Bool enableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +#if NeedFunctionPrototypes +SetWindowToDefaults(register WindowPtr pWin) +#else +SetWindowToDefaults(pWin) + register WindowPtr pWin; +#endif +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +} + +static void +#if NeedFunctionPrototypes +MakeRootTile(WindowPtr pWin) +#else +MakeRootTile(pWin) + WindowPtr pWin; +#endif +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + GCPtr pGC; + unsigned char back[128]; + int len = BitmapBytePad(sizeof(long)); + register unsigned char *from, *to; + register int i, j; + + pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4, + pScreen->rootDepth); + + pWin->backgroundState = BackgroundPixmap; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pWin->background.pixmap || !pGC) + FatalError("could not create root tile"); + + { + CARD32 attributes[2]; + + attributes[0] = pScreen->whitePixel; + attributes[1] = pScreen->blackPixel; + + (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); + } + + ValidateGC((DrawablePtr)pWin->background.pixmap, pGC); + + from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb; + to = back; + + for (i = 4; i > 0; i--, from++) + for (j = len; j > 0; j--) + *to++ = *from; + + if (blackRoot) + bzero(back, sizeof(back)); + + (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, + 0, 0, len, 4, 0, XYBitmap, (char *)back); + + FreeScratchGC(pGC); + +} + +WindowPtr +AllocateWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(pScreen) + ScreenPtr pScreen; +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + pScreen->backingStoreSupport = NotUseful; + if (enableBackingStore) + pScreen->backingStoreSupport = Always; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +void +InitRootWindow(pWin) + WindowPtr pWin; +{ + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + MakeRootTile(pWin); + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + + MapWindow(pWin, serverClient); +} + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(pWin, Rgn, x, y, w, h) + register WindowPtr pWin; + RegionPtr Rgn; + register int x, y; + int w, h; +{ + REGION_PTR(pScreen, pWin) + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +WindowPtr +RealChildHead(pWin) + register WindowPtr pWin; +{ + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +WindowPtr +CreateWindow(wid, pParent, x, y, w, h, bw, class, vmask, vlist, + depth, client, visual, error) + Window wid; + register WindowPtr pParent; + int x,y; + unsigned int w, h, bw; + unsigned int class; + register Mask vmask; + XID *vlist; + int depth; + ClientPtr client; + VisualID visual; + int *error; +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (client->trustLevel != XSecurityClientTrusted) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_INIT(pScreen, &pWin->clipList, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderClip, NullBox, 1); + REGION_INIT(pScreen, &pWin->winSize, NullBox, 1); + REGION_INIT(pScreen, &pWin->borderSize, NullBox, 1); + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + return pWin; +} + +static void +#if NeedFunctionPrototypes +FreeWindowResources(register WindowPtr pWin) +#else +FreeWindowResources(pWin) + register WindowPtr pWin; +#endif +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +#if NeedFunctionPrototypes +CrushTree(WindowPtr pWin) +#else +CrushTree(pWin) + WindowPtr pWin; +#endif +{ + register WindowPtr pChild, pSib, pParent; + UnrealizeWindowProcPtr UnrealizeWindow; + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +/*ARGSUSED*/ +int +DeleteWindow(value, wid) + pointer value; + XID wid; + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + xfree(pWin); + return Success; +} + +/*ARGSUSED*/ +void +DestroySubwindows(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +int +ChangeWindowAttributes(pWin, vmask, vlist, client) + register WindowPtr pWin; + Mask vmask; + XID *vlist; + ClientPtr client; +{ + register Mask index2; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index2 = (Mask) lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows */ + if (client->trustLevel == XSecurityClientTrusted) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XCSECURITY + } + else + { /* didn't change the background to None, so don't tell ddx */ + index2 = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index2 = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == (CARD32)~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if ( win_owner && win_owner->appgroup && + !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index2; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_INIT(pScreen, &exposed, NullBox, 0); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(pWin, client, wa) + register WindowPtr pWin; + ClientPtr client; + xGetWindowAttributesReply *wa; +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +WindowPtr +MoveWindowInStack(pWin, pNextSib) + register WindowPtr pWin, pNextSib; +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + WindowPtr pOldNextSib = pWin->nextSib; + + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + if(pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); + } + + return( pFirstChange ); +} + +RegionPtr +CreateUnclippedWinSize (pWin) + register WindowPtr pWin; +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +void +SetWinSize (pWin) + register WindowPtr pWin; +{ + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +void +SetBorderSize (pWin) + register WindowPtr pWin; +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { + REGION_PTR(pScreen, pWin) + + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +void +GravityTranslate (x, y, oldx, oldy, dw, dh, gravity, destx, desty) + register int x, y; /* new window position */ + int oldx, oldy; /* old window position */ + int dw, dh; + unsigned gravity; + register int *destx, *desty; /* position relative to gravity */ +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +void +ResizeChildrenWinSize(pWin, dx, dy, dw, dh) + register WindowPtr pWin; + int dx, dy, dw, dh; +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + (*pScreen->PositionWindow)(pChild, + pChild->drawable.x, pChild->drawable.y); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +#if NeedFunctionPrototypes +IsSiblingAboveMe( + register WindowPtr pMe, + register WindowPtr pSib) +#else +IsSiblingAboveMe(pMe, pSib) + register WindowPtr pMe, pSib; +#endif +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +#if NeedFunctionPrototypes +WindowExtents( + register WindowPtr pWin, + register BoxPtr pBox) +#else +WindowExtents(pWin, pBox) + register WindowPtr pWin; + register BoxPtr pBox; +#endif +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +#if NeedFunctionPrototypes +MakeBoundingRegion ( + register WindowPtr pWin, + BoxPtr pBox) +#else +MakeBoundingRegion (pWin, pBox) + register WindowPtr pWin; + BoxPtr pBox; +#endif +{ + RegionPtr pRgn; + REGION_PTR(pScreen, pWin) + + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +#if NeedFunctionPrototypes +ShapeOverlap ( + WindowPtr pWin, + BoxPtr pWinBox, + WindowPtr pSib, + BoxPtr pSibBox) +#else +ShapeOverlap (pWin, pWinBox, pSib, pSibBox) + WindowPtr pWin, pSib; + BoxPtr pWinBox, pSibBox; +#endif +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +#if NeedFunctionPrototypes +AnyWindowOverlapsMe( + WindowPtr pWin, + WindowPtr pHead, + register BoxPtr box) +#else +AnyWindowOverlapsMe(pWin, pHead, box) + WindowPtr pWin, pHead; + register BoxPtr box; +#endif +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +#if NeedFunctionPrototypes +IOverlapAnyWindow( + WindowPtr pWin, + register BoxPtr box) +#else +IOverlapAnyWindow(pWin, box) + WindowPtr pWin; + register BoxPtr box; +#endif +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +#if NeedFunctionPrototypes +WhereDoIGoInTheStack( + register WindowPtr pWin, + register WindowPtr pSib, + short x, + short y, + unsigned short w, + unsigned short h, + int smode) +#else +WhereDoIGoInTheStack(pWin, pSib, x, y, w, h, smode) + register WindowPtr pWin, pSib; + short x, y; + unsigned short w, h; + int smode; +#endif +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +#if NeedFunctionPrototypes +ReflectStackChange( + register WindowPtr pWin, + register WindowPtr pSib, + VTKind kind) +#else +ReflectStackChange(pWin, pSib, kind) + register WindowPtr pWin, pSib; + VTKind kind; +#endif +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + WindowPtr pParent; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!(pParent = pWin->parent)) + return ; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(pWin, mask, vlist, client) + register WindowPtr pWin; + register Mask mask; + XID *vlist; + ClientPtr client; +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid = 0; + Mask index2, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index2 = (Mask)lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureRequest.x += panoramiXdataPtr[0].x; + event.u.configureRequest.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { + if (pWin->nextSib != pSib) + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureNotify.x += panoramiXdataPtr[0].x; + event.u.configureNotify.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(pParent, direction, client) + WindowPtr pParent; + int direction; + ClientPtr client; +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +#if NeedFunctionPrototypes +CompareWIDs( + WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +#else +CompareWIDs(pWin, value) + WindowPtr pWin; + pointer value; /* must conform to VisitWindowProcPtr */ +#endif +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(pWin, pParent, x, y, client) + register WindowPtr pWin, pParent; + int x,y; + ClientPtr client; +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pParent->parent) { + event.u.reparent.x += panoramiXdataPtr[0].x; + event.u.reparent.y += panoramiXdataPtr[0].y; + } +#endif + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +#if NeedFunctionPrototypes +RealizeTree(WindowPtr pWin) +#else +RealizeTree(pWin) + WindowPtr pWin; +#endif +{ + register WindowPtr pChild; + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +int +MapWindow(pWin, client) + register WindowPtr pWin; + ClientPtr client; +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (pWin->mapped) + return(Success); + +#ifdef XCSECURITY + /* don't let an untrusted client map a child-of-trusted-window, InputOnly + * window; too easy to steal device input + */ + if ( (client->trustLevel != XSecurityClientTrusted) && + (pWin->drawable.class == InputOnly) && + (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) ) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_INIT(pScreen, &temp, NullBox, 0); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(pParent, client) + register WindowPtr pParent; + ClientPtr client; +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +#if NeedFunctionPrototypes +UnrealizeTree( + WindowPtr pWin, + Bool fromConfigure) +#else +UnrealizeTree(pWin, fromConfigure) + WindowPtr pWin; + Bool fromConfigure; +#endif +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { + PanoramiXRes *win; + win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, + XRT_WINDOW); + if(win) + win->u.win.visibility = VisibilityNotViewable; + } +#endif + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +int +UnmapWindow(pWin, fromConfigure) + register WindowPtr pWin; + Bool fromConfigure; +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(pWin) + register WindowPtr pWin; +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin = NULL; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(client) + register ClientPtr client; +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; jnumSaved; j++) + { + pWin = (WindowPtr)client->saveSet[j]; + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (pointer *)NULL; +} + +Bool +VisibleBoundingBoxFromPoint(pWin, x, y, box) + register WindowPtr pWin; + int x, y; /* in root */ + BoxPtr box; /* "return" value */ +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +Bool +PointInWindowIsVisible(pWin, x, y) + register WindowPtr pWin; + int x, y; /* in root */ +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box)) + return(TRUE); + return(FALSE); +} + + +RegionPtr +NotClippedByChildren(pWin) + register WindowPtr pWin; +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + +void +SendVisibilityNotify(pWin) + WindowPtr pWin; +{ + xEvent event; + unsigned int visibility = pWin->visibility; + +#ifdef PANORAMIX + /* This is not quite correct yet, but it's close */ + if(!noPanoramiXExtension) { + PanoramiXRes *win; + WindowPtr pWin2; + int i, Scrnum; + + Scrnum = pWin->drawable.pScreen->myNum; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); + + if(!win || (win->u.win.visibility == visibility)) + return; + + switch(visibility) { + case VisibilityUnobscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility == VisibilityPartiallyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + case VisibilityPartiallyObscured: + if(Scrnum) { + pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); + if (pWin2) pWin = pWin2; + } + break; + case VisibilityFullyObscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility != VisibilityFullyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + } + + win->u.win.visibility = visibility; + } +#endif + + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +static void DrawLogo( +#if NeedFunctionPrototypes + WindowPtr /*pWin*/ +#endif +); +#endif + +void +SaveScreens(on, mode) + int on; + int mode; +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + /* + * Call the DDX saver in case it wants to do something + * at cycle time + */ + else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + type); + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; +} + +static Bool +#if NeedFunctionPrototypes +TileScreenSaver(int i, int kind) +#else +TileScreenSaver(i, kind) + int i; + int kind; +#endif +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID = 0; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; jwidth + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +WindowPtr +FindWindowWithOptional (w) + register WindowPtr w; +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +void +CheckWindowOptionalNeed (w) + register WindowPtr w; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +Bool +MakeWindowOptional (pWin) + register WindowPtr pWin; +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (pWin) + register WindowPtr pWin; +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + /* + * TOG changed this code to: + * + * if (pWin->cursorIsNone == FALSE) + * FreeCursor (pWin->optional->cursor, (Cursor)0); + * pWin->cursorIsNone = TRUE; + * + * This is blatently wrong; windows without optionals can have + * two different cursor values, either None or sharing their + * parents cursor. This difference is controlled by the + * cursorIsNone value; when TRUE, the window has no cursor, + * when false, it shares its cursor with its parent; TOG + * made it impossible for a window to have a cursor without + * an optional record. + */ + if (pWin->optional->cursor) + { + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = FALSE; + } + else + pWin->cursorIsNone = TRUE; + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +#if NeedFunctionPrototypes +DrawLogo(WindowPtr pWin) +#else +DrawLogo(pWin) + WindowPtr pWin; +#endif +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.c b/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.c new file mode 100644 index 000000000..91dafb6c6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.c @@ -0,0 +1,755 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/lib/Xrandr/Xrandr.c,v 1.13tsi Exp $ + * + * Copyright © 2000 Compaq Computer Corporation, Inc. + * Copyright © 2002 Hewlett Packard Company, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, HP. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +/* we need to be able to manipulate the Display structure on events */ +#include +#include +#include + +#include "NXxrandrint.h" + +XExtensionInfo XRRExtensionInfo; +char XRRExtensionName[] = RANDR_NAME; + +static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire); +static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire); + +static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window); + +static int +XRRCloseDisplay (Display *dpy, XExtCodes *codes); + +static /* const */ XExtensionHooks rr_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + XRRCloseDisplay, /* close_display */ + XRRWireToEvent, /* wire_to_event */ + XRREventToWire, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static Bool XRRWireToEvent(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + XRRScreenChangeNotifyEvent *aevent; + xRRScreenChangeNotifyEvent *awire; + + RRCheckExtension(dpy, info, False); + + switch ((wire->u.u.type & 0x7F) - info->codes->first_event) + { + case RRScreenChangeNotify: + awire = (xRRScreenChangeNotifyEvent *) wire; + aevent = (XRRScreenChangeNotifyEvent *) event; + aevent->type = awire->type & 0x7F; + aevent->serial = _XSetLastRequestRead(dpy, + (xGenericReply *) wire); + aevent->send_event = (awire->type & 0x80) != 0; + aevent->display = dpy; + aevent->window = awire->window; + aevent->root = awire->root; + aevent->timestamp = awire->timestamp; + aevent->config_timestamp = awire->configTimestamp; + aevent->size_index = awire->sizeID; + aevent->subpixel_order = awire->subpixelOrder; + aevent->rotation = awire->rotation; + aevent->width = awire->widthInPixels; + aevent->height = awire->heightInPixels; + aevent->mwidth = awire->widthInMillimeters; + aevent->mheight = awire->heightInMillimeters; + return True; + } + + return False; +} + +static Status XRREventToWire(Display *dpy, XEvent *event, xEvent *wire) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + XRRScreenChangeNotifyEvent *aevent; + xRRScreenChangeNotifyEvent *awire; + + RRCheckExtension(dpy, info, False); + + switch ((event->type & 0x7F) - info->codes->first_event) + { + case RRScreenChangeNotify: + awire = (xRRScreenChangeNotifyEvent *) wire; + aevent = (XRRScreenChangeNotifyEvent *) event; + awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); + awire->rotation = (CARD8) aevent->rotation; + awire->sequenceNumber = aevent->serial & 0xFFFF; + awire->timestamp = aevent->timestamp; + awire->configTimestamp = aevent->config_timestamp; + awire->root = aevent->root; + awire->window = aevent->window; + awire->sizeID = aevent->size_index; + awire->subpixelOrder = aevent->subpixel_order; + awire->widthInPixels = aevent->width; + awire->heightInPixels = aevent->height; + awire->widthInMillimeters = aevent->mwidth; + awire->heightInMillimeters = aevent->mheight; + return True; + } + return False; +} + +XExtDisplayInfo * +XRRFindDisplay (Display *dpy) +{ + XExtDisplayInfo *dpyinfo; + XRandRInfo *xrri; + int i, numscreens; + + dpyinfo = XextFindDisplay (&XRRExtensionInfo, dpy); + if (!dpyinfo) { + dpyinfo = XextAddDisplay (&XRRExtensionInfo, dpy, + XRRExtensionName, + &rr_extension_hooks, + RRNumberEvents, 0); + numscreens = ScreenCount(dpy); + xrri = Xmalloc (sizeof(XRandRInfo) + + sizeof(char *) * numscreens); + xrri->config = (XRRScreenConfiguration **)(xrri + 1); + for(i = 0; i < numscreens; i++) + xrri->config[i] = NULL; + xrri->major_version = -1; + dpyinfo->data = (char *) xrri; + } + return dpyinfo; +} + +static int +XRRCloseDisplay (Display *dpy, XExtCodes *codes) +{ + int i; + XRRScreenConfiguration **configs; + XExtDisplayInfo *info = XRRFindDisplay (dpy); + XRandRInfo *xrri; + + LockDisplay(dpy); + /* + * free cached data + */ + if (XextHasExtension(info)) { + xrri = (XRandRInfo *) info->data; + if (xrri) { + configs = xrri->config; + + for (i = 0; i < ScreenCount(dpy); i++) { + if (configs[i] != NULL) XFree (configs[i]); + } + XFree (xrri); + } + } + UnlockDisplay(dpy); + return XextRemoveDisplay (&XRRExtensionInfo, dpy); +} + + +Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation) +{ + *current_rotation = config->current_rotation; + return config->rotations; +} + +XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes) +{ + *nsizes = config->nsizes; + return config->sizes; +} + +short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates) +{ + short *r = config->rates; + int nents = config->nrates; + + /* Skip over the intervening rate lists */ + while (sizeID > 0 && nents > 0) + { + int i = (*r + 1); + r += i; + nents -= i; + sizeID--; + } + if (!nents) + { + *nrates = 0; + return 0; + } + *nrates = (int) *r; + return r + 1; +} + +Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp) +{ + *config_timestamp = config->config_timestamp; + return config->timestamp; +} + + +SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config, + Rotation *rotation) +{ + *rotation = (Rotation) config->current_rotation; + return (SizeID) config->current_size; +} + +short XRRConfigCurrentRate (XRRScreenConfiguration *config) +{ + return config->current_rate; +} + +/* + * Go get the screen configuration data and salt it away for future use; + * returns NULL if extension not supported + */ +static XRRScreenConfiguration *_XRRValidateCache (Display *dpy, int screen) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + XRRScreenConfiguration **configs; + XRandRInfo *xrri; + + if (XextHasExtension(info)) { + xrri = (XRandRInfo *) info->data; + configs = xrri->config; + + if (configs[screen] == NULL) + configs[screen] = _XRRGetScreenInfo (dpy, RootWindow(dpy, screen)); + return configs[screen]; + } else { + return NULL; + } +} + +/* given a screen, return the information from the (possibly) cached data */ +Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation) +{ + XRRScreenConfiguration *config; + Rotation cr; + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + *current_rotation = config->current_rotation; + cr = config->rotations; + UnlockDisplay(dpy); + return cr; + } + else { + UnlockDisplay(dpy); + *current_rotation = RR_Rotate_0; + return 0; /* no rotations supported */ + } +} + +/* given a screen, return the information from the (possibly) cached data */ +XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes) +{ + XRRScreenConfiguration *config; + XRRScreenSize *sizes; + + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + *nsizes = config->nsizes; + sizes = config->sizes; + UnlockDisplay(dpy); + return sizes; + } + else { + UnlockDisplay(dpy); + *nsizes = 0; + return NULL; + } +} + +short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates) +{ + XRRScreenConfiguration *config; + short *rates; + + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + rates = XRRConfigRates (config, sizeID, nrates); + UnlockDisplay(dpy); + return rates; + } + else { + UnlockDisplay(dpy); + *nrates = 0; + return NULL; + } +} + +/* given a screen, return the information from the (possibly) cached data */ +Time XRRTimes (Display *dpy, int screen, Time *config_timestamp) +{ + XRRScreenConfiguration *config; + Time ts; + + LockDisplay(dpy); + if ((config = _XRRValidateCache(dpy, screen))) { + *config_timestamp = config->config_timestamp; + ts = config->timestamp; + UnlockDisplay(dpy); + return ts; + } else { + UnlockDisplay(dpy); + return CurrentTime; + } +} + +int XRRRootToScreen(Display *dpy, Window root) +{ + int snum; + for (snum = 0; snum < ScreenCount(dpy); snum++) { + if (RootWindow(dpy, snum) == root) return snum; + } + return -1; +} + + +Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + +static Bool +_XRRHasRates (int major, int minor) +{ + return major > 1 || (major == 1 && minor >= 1); +} + +Status XRRQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + xRRQueryVersionReply rep; + xRRQueryVersionReq *req; + XRandRInfo *xrri; + + RRCheckExtension (dpy, info, 0); + + xrri = (XRandRInfo *) info->data; + + /* + * only get the version information from the server if we don't have it already + */ + if (xrri->major_version == -1) { + LockDisplay (dpy); + GetReq (RRQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRQueryVersion; + req->majorVersion = RANDR_MAJOR; + req->minorVersion = RANDR_MINOR; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + xrri->major_version = rep.majorVersion; + xrri->minor_version = rep.minorVersion; + xrri->has_rates = _XRRHasRates (xrri->major_version, xrri->minor_version); + } + *major_versionp = xrri->major_version; + *minor_versionp = xrri->minor_version; + UnlockDisplay (dpy); + SyncHandle (); + return 1; +} + +typedef struct _randrVersionState { + unsigned long version_seq; + Bool error; + int major_version; + int minor_version; +} _XRRVersionState; + +static Bool +_XRRVersionHandler (Display *dpy, + xReply *rep, + char *buf, + int len, + XPointer data) +{ + xRRQueryVersionReply replbuf; + xRRQueryVersionReply *repl; + _XRRVersionState *state = (_XRRVersionState *) data; + + if (dpy->last_request_read != state->version_seq) + return False; + if (rep->generic.type == X_Error) + { + state->error = True; + return False; + } + repl = (xRRQueryVersionReply *) + _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, + (SIZEOF(xRRQueryVersionReply) - SIZEOF(xReply)) >> 2, + True); + state->major_version = repl->majorVersion; + state->minor_version = repl->minorVersion; + return True; +} +/* need a version that does not hold the display lock */ +static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy, Window window) +{ + XExtDisplayInfo *info = XRRFindDisplay(dpy); + xRRGetScreenInfoReply rep; + xRRGetScreenInfoReq *req; + _XAsyncHandler async; + _XRRVersionState async_state; + int nbytes, nbytesRead, rbytes; + int i; + xScreenSizes size; + struct _XRRScreenConfiguration *scp; + XRRScreenSize *ssp; + short *rates; + xRRQueryVersionReq *vreq; + XRandRInfo *xrri; + Bool getting_version = False; + + RRCheckExtension (dpy, info, 0); + + xrri = (XRandRInfo *) info->data; + + if (xrri->major_version == -1) + { + /* hide a version query in the request */ + GetReq (RRQueryVersion, vreq); + vreq->reqType = info->codes->major_opcode; + vreq->randrReqType = X_RRQueryVersion; + vreq->majorVersion = RANDR_MAJOR; + vreq->minorVersion = RANDR_MINOR; + + async_state.version_seq = dpy->request; + async_state.error = False; + async.next = dpy->async_handlers; + async.handler = _XRRVersionHandler; + async.data = (XPointer) &async_state; + dpy->async_handlers = &async; + + getting_version = True; + } + + GetReq (RRGetScreenInfo, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRGetScreenInfo; + req->window = window; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) + { + if (getting_version) + DeqAsyncHandler (dpy, &async); + SyncHandle (); + return NULL; + } + if (getting_version) + { + DeqAsyncHandler (dpy, &async); + if (async_state.error) + { + SyncHandle(); + } + xrri->major_version = async_state.major_version; + xrri->minor_version = async_state.minor_version; + xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version); + } + + /* + * Make the reply compatible with v1.1 + */ + if (!xrri->has_rates) + { + rep.rate = 0; + rep.nrateEnts = 0; + } + + nbytes = (long) rep.length << 2; + + nbytesRead = (long) (rep.nSizes * SIZEOF (xScreenSizes) + + ((rep.nrateEnts + 1)& ~1) * 2 /* SIZEOF (CARD16) */); + + /* + * first we must compute how much space to allocate for + * randr library's use; we'll allocate the structures in a single + * allocation, on cleanlyness grounds. + */ + + rbytes = sizeof (XRRScreenConfiguration) + + (rep.nSizes * sizeof (XRRScreenSize) + + rep.nrateEnts * sizeof (int)); + + scp = (struct _XRRScreenConfiguration *) Xmalloc(rbytes); + if (scp == NULL) { + _XEatData (dpy, (unsigned long) nbytes); + SyncHandle (); + return NULL; + } + + + ssp = (XRRScreenSize *)(scp + 1); + rates = (short *) (ssp + rep.nSizes); + + /* set up the screen configuration structure */ + scp->screen = + ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root)); + + scp->sizes = ssp; + scp->rates = rates; + scp->rotations = rep.setOfRotations; + scp->current_size = rep.sizeID; + scp->current_rate = rep.rate; + scp->current_rotation = rep.rotation; + scp->timestamp = rep.timestamp; + scp->config_timestamp = rep.configTimestamp; + scp->nsizes = rep.nSizes; + scp->nrates = rep.nrateEnts; + + /* + * Time to unpack the data from the server. + */ + + /* + * First the size information + */ + for (i = 0; i < rep.nSizes; i++) { + _XReadPad (dpy, (char *) &size, SIZEOF (xScreenSizes)); + + ssp[i].width = size.widthInPixels; + ssp[i].height = size.heightInPixels; + ssp[i].mwidth = size.widthInMillimeters; + ssp[i].mheight = size.heightInMillimeters; + } + /* + * And the rates + */ + _XRead16Pad (dpy, rates, 2 /* SIZEOF (CARD16) */ * rep.nrateEnts); + + /* + * Skip any extra data + */ + if (nbytes > nbytesRead) + _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); + + return (XRRScreenConfiguration *)(scp); +} + +XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, Window window) +{ + XRRScreenConfiguration *config; + XRRFindDisplay(dpy); + LockDisplay (dpy); + config = _XRRGetScreenInfo(dpy, window); + UnlockDisplay (dpy); + SyncHandle (); + return config; +} + + +void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config) +{ + Xfree (config); +} + + +/* + * in protocol version 0.1, routine added to allow selecting for new events. + */ + +void XRRSelectInput (Display *dpy, Window window, int mask) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + xRRSelectInputReq *req; + + RRSimpleCheckExtension (dpy, info); + + LockDisplay (dpy); + GetReq (RRSelectInput, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSelectInput; + req->window = window; + req->enable = 0; + if (mask) req->enable = mask; + UnlockDisplay (dpy); + SyncHandle (); + return; +} + +Status XRRSetScreenConfigAndRate (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + Rotation rotation, + short rate, + Time timestamp) +{ + XExtDisplayInfo *info = XRRFindDisplay (dpy); + xRRSetScreenConfigReply rep; + XRandRInfo *xrri; + int major, minor; + + RRCheckExtension (dpy, info, 0); + + /* Make sure has_rates is set */ + if (!XRRQueryVersion (dpy, &major, &minor)) + return 0; + + LockDisplay (dpy); + xrri = (XRandRInfo *) info->data; + if (xrri->has_rates) + { + xRRSetScreenConfigReq *req; + GetReq (RRSetScreenConfig, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetScreenConfig; + req->drawable = draw; + req->sizeID = size_index; + req->rotation = rotation; + req->timestamp = timestamp; + req->configTimestamp = config->config_timestamp; + req->rate = rate; + } + else + { + xRR1_0SetScreenConfigReq *req; + GetReq (RR1_0SetScreenConfig, req); + req->reqType = info->codes->major_opcode; + req->randrReqType = X_RRSetScreenConfig; + req->drawable = draw; + req->sizeID = size_index; + req->rotation = rotation; + req->timestamp = timestamp; + req->configTimestamp = config->config_timestamp; + } + + (void) _XReply (dpy, (xReply *) &rep, 0, xTrue); + + if (rep.status == RRSetConfigSuccess) { + /* if we succeed, set our view of reality to what we set it to */ + config->config_timestamp = rep.newConfigTimestamp; + config->timestamp = rep.newTimestamp; + config->screen = ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root)); + config->current_size = size_index; + config->current_rotation = rotation; + } + UnlockDisplay (dpy); + SyncHandle (); + return(rep.status); +} + +Status XRRSetScreenConfig (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + Rotation rotation, Time timestamp) +{ + return XRRSetScreenConfigAndRate (dpy, config, draw, size_index, + rotation, 0, timestamp); +} + +int XRRUpdateConfiguration(XEvent *event) +{ + XRRScreenChangeNotifyEvent *scevent; + XConfigureEvent *rcevent; + Display *dpy = event->xany.display; + XExtDisplayInfo *info; + XRandRInfo *xrri; + int snum; + + /* first, see if it is a vanilla configure notify event */ + if (event->type == ConfigureNotify) { + rcevent = (XConfigureEvent *) event; + snum = XRRRootToScreen(dpy, rcevent->window); + dpy->screens[snum].width = rcevent->width; + dpy->screens[snum].height = rcevent->height; + return 1; + } + + info = XRRFindDisplay(dpy); + RRCheckExtension (dpy, info, 0); + + switch (event->type - info->codes->first_event) { + case RRScreenChangeNotify: + scevent = (XRRScreenChangeNotifyEvent *) event; + snum = XRRRootToScreen(dpy, + ((XRRScreenChangeNotifyEvent *) event)->root); + dpy->screens[snum].width = scevent->width; + dpy->screens[snum].height = scevent->height; + dpy->screens[snum].mwidth = scevent->mwidth; + dpy->screens[snum].mheight = scevent->mheight; + XRenderSetSubpixelOrder (dpy, snum, scevent->subpixel_order); + break; + default: + return 0; + } + xrri = (XRandRInfo *) info->data; + /* + * so the next time someone wants some data, it will be fetched; + * it might be better to force the round trip immediately, but + * I dislike pounding the server simultaneously when not necessary + */ + if (xrri->config[snum] != NULL) { + XFree (xrri->config[snum]); + xrri->config[snum] = NULL; + } + return 1; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.h b/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.h new file mode 100644 index 000000000..3fb504ea9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.h @@ -0,0 +1,168 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/lib/Xrandr/Xrandr.h,v 1.9 2002/09/29 23:39:44 keithp Exp $ + * + * Copyright © 2000 Compaq Computer Corporation, Inc. + * Copyright © 2002 Hewlett-Packard Company, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL COMPAQ + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, HP. + */ + +#ifndef _XRANDR_H_ +#define _XRANDR_H_ + +#include + +#include + +_XFUNCPROTOBEGIN + + +typedef struct { + int width, height; + int mwidth, mheight; +} XRRScreenSize; + +/* + * Events. + */ + +typedef struct { + int type; /* event base */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* window which selected for this event */ + Window root; /* Root window for changed screen */ + Time timestamp; /* when the screen change occurred */ + Time config_timestamp; /* when the last configuration change */ + SizeID size_index; + SubpixelOrder subpixel_order; + Rotation rotation; + int width; + int height; + int mwidth; + int mheight; +} XRRScreenChangeNotifyEvent; + + +/* internal representation is private to the library */ +typedef struct _XRRScreenConfiguration XRRScreenConfiguration; + +Bool XRRQueryExtension (Display *dpy, int *event_basep, int *error_basep); +Status XRRQueryVersion (Display *dpy, + int *major_versionp, + int *minor_versionp); + +XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, + Drawable draw); + +void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config); + +/* + * Note that screen configuration changes are only permitted if the client can + * prove it has up to date configuration information. We are trying to + * insist that it become possible for screens to change dynamically, so + * we want to ensure the client knows what it is talking about when requesting + * changes. + */ +Status XRRSetScreenConfig (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + Rotation rotation, + Time timestamp); + +/* added in v1.1, sorry for the lame name */ +Status XRRSetScreenConfigAndRate (Display *dpy, + XRRScreenConfiguration *config, + Drawable draw, + int size_index, + Rotation rotation, + short rate, + Time timestamp); + + +Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation); + +Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp); + +XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes); + +short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates); + +SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config, + Rotation *rotation); + +short XRRConfigCurrentRate (XRRScreenConfiguration *config); + +int XRRRootToScreen(Display *dpy, Window root); + +/* + * returns the screen configuration for the specified screen; does a lazy + * evalution to delay getting the information, and caches the result. + * These routines should be used in preference to XRRGetScreenInfo + * to avoid unneeded round trips to the X server. These are new + * in protocol version 0.1. + */ + + +XRRScreenConfiguration *XRRScreenConfig(Display *dpy, int screen); +XRRScreenConfiguration *XRRConfig(Screen *screen); +void XRRSelectInput(Display *dpy, Window window, int mask); + +/* + * the following are always safe to call, even if RandR is not implemented + * on a screen + */ + + +Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation); +XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes); +short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates); +Time XRRTimes (Display *dpy, int screen, Time *config_timestamp); + + +/* + * intended to take RRScreenChangeNotify, or + * ConfigureNotify (on the root window) + * returns 1 if it is an event type it understands, 0 if not + */ +int XRRUpdateConfiguration(XEvent *event); + +_XFUNCPROTOEND + +#endif /* _XRANDR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXxrandrint.h b/nx-X11/programs/Xserver/hw/nxagent/NXxrandrint.h new file mode 100644 index 000000000..33b05b1f0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXxrandrint.h @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/lib/Xrandr/Xrandrint.h,v 1.2 2001/06/07 15:33:43 keithp Exp $ + * + * + * Copyright © 2000, Compaq Computer Corporation, + * Copyright © 2002, Hewlett Packard, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + */ + +#ifndef _XRANDRINT_H_ +#define _XRANDRINT_H_ + +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include +#include +#include +#include +#include +#include "NXxrandr.h" + +extern XExtensionInfo XrandrExtensionInfo; +extern char XrandrExtensionName[]; + +#define RRCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, XRRExtensionName, val) +#define RRSimpleCheckExtension(dpy,i) \ + XextSimpleCheckExtension (dpy, i, XRRExtensionName) + +XExtDisplayInfo *XRRFindDisplay (Display *dpy); + + +/* deliberately opaque internal data structure; can be extended, + but not reordered */ +struct _XRRScreenConfiguration { + Screen *screen; /* the root window in GetScreenInfo */ + XRRScreenSize *sizes; + Rotation rotations; + Rotation current_rotation; + int nsizes; + int current_size; + short current_rate; + Time timestamp; + Time config_timestamp; + int subpixel_order; /* introduced in randr v0.1 */ + short *rates; /* introduced in randr v1.1 */ + int nrates; +}; + +/* + * if a configure notify on the root is recieved, or + * an XRRScreenChangeNotify is recieved, + * XRRUpdateConfiguration should be called to update the X library's + * view of the screen configuration; it will also invalidate the cache + * provided by XRRScreenConfig and XRRConfig, and force a round trip + * when next used. Returns invalid status if not an event type + * the library routine understand. + */ + +/* we cache one screen configuration/screen */ + +typedef struct _XRandRInfo { + XRRScreenConfiguration **config; + int major_version, minor_version; /* major_version = -1 means we don't know */ + Bool has_rates; /* Server supports refresh rates */ +} XRandRInfo; + +#endif /* _XRANDRINT_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c new file mode 100644 index 000000000..f3bfcf58a --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c @@ -0,0 +1,2277 @@ +#ifdef NXAGENT_UPGRADE + +#if !defined(__sun) && !defined(__CYGWIN__) + +#include "X/NXxvdisp.c" + +#endif + +#else + +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdisp.c,v 1.25 2001/11/18 23:55:48 mvojkovi Exp $ */ + +/* +** File: +** +** xvdisp.c --- Xv server extension dispatch module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include "Xv.h" +#include "Xvproto.h" +#include "xvdix.h" +#ifdef MITSHM +#define _XSHM_SERVER_ +#include "shmstr.h" +#endif + +#include "Trap.h" + +#undef TEST +#undef DEBUG + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; + +#ifdef MITSHM +static int XineramaXvShmPutImage(ClientPtr); +#endif +static int XineramaXvPutImage(ClientPtr); +static int XineramaXvPutVideo(ClientPtr); +static int XineramaXvPutStill(ClientPtr); +static int XineramaXvSetPortAttribute(ClientPtr); +static int XineramaXvStopVideo(ClientPtr); +#endif + +/* INTERNAL */ + +static int ProcXvQueryExtension(ClientPtr); +static int ProcXvQueryAdaptors(ClientPtr); +static int ProcXvQueryEncodings(ClientPtr); +static int ProcXvPutVideo(ClientPtr); +static int ProcXvPutStill(ClientPtr); +static int ProcXvGetVideo(ClientPtr); +static int ProcXvGetStill(ClientPtr); +static int ProcXvGrabPort(ClientPtr); +static int ProcXvUngrabPort(ClientPtr); +static int ProcXvSelectVideoNotify(ClientPtr); +static int ProcXvSelectPortNotify(ClientPtr); +static int ProcXvStopVideo(ClientPtr); +static int ProcXvSetPortAttribute(ClientPtr); +static int ProcXvGetPortAttribute(ClientPtr); +static int ProcXvQueryBestSize(ClientPtr); +static int ProcXvQueryPortAttributes(ClientPtr); +static int ProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int ProcXvShmPutImage(ClientPtr); +#endif +static int ProcXvQueryImageAttributes(ClientPtr); +static int ProcXvListImageFormats(ClientPtr); + +static int SProcXvQueryExtension(ClientPtr); +static int SProcXvQueryAdaptors(ClientPtr); +static int SProcXvQueryEncodings(ClientPtr); +static int SProcXvPutVideo(ClientPtr); +static int SProcXvPutStill(ClientPtr); +static int SProcXvGetVideo(ClientPtr); +static int SProcXvGetStill(ClientPtr); +static int SProcXvGrabPort(ClientPtr); +static int SProcXvUngrabPort(ClientPtr); +static int SProcXvSelectVideoNotify(ClientPtr); +static int SProcXvSelectPortNotify(ClientPtr); +static int SProcXvStopVideo(ClientPtr); +static int SProcXvSetPortAttribute(ClientPtr); +static int SProcXvGetPortAttribute(ClientPtr); +static int SProcXvQueryBestSize(ClientPtr); +static int SProcXvQueryPortAttributes(ClientPtr); +static int SProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int SProcXvShmPutImage(ClientPtr); +#endif +static int SProcXvQueryImageAttributes(ClientPtr); +static int SProcXvListImageFormats(ClientPtr); + +static int SWriteQueryAdaptorsReply(ClientPtr, xvQueryAdaptorsReply *); +static int SWriteQueryExtensionReply(ClientPtr, xvQueryExtensionReply *); +static int SWriteQueryEncodingsReply(ClientPtr, xvQueryEncodingsReply *); +static int SWriteAdaptorInfo(ClientPtr, xvAdaptorInfo *); +static int SWriteEncodingInfo(ClientPtr, xvEncodingInfo *); +static int SWriteFormat(ClientPtr, xvFormat *); +static int SWriteAttributeInfo(ClientPtr, xvAttributeInfo *); +static int SWriteGrabPortReply(ClientPtr, xvGrabPortReply *); +static int SWriteGetPortAttributeReply(ClientPtr, xvGetPortAttributeReply *); +static int SWriteQueryBestSizeReply(ClientPtr, xvQueryBestSizeReply *); +static int SWriteQueryPortAttributesReply( + ClientPtr, xvQueryPortAttributesReply *); +static int SWriteQueryImageAttributesReply( + ClientPtr, xvQueryImageAttributesReply*); +static int SWriteListImageFormatsReply(ClientPtr, xvListImageFormatsReply*); +static int SWriteImageFormatInfo(ClientPtr, xvImageFormatInfo*); + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +/* +** ProcXvDispatch +** +** +** +*/ + +int +ProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (ProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (ProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (ProcXvQueryEncodings(client)); break; + case xv_PutVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutVideo(client)); break; + else +#endif + result = (ProcXvPutVideo(client)); break; + case xv_PutStill: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutStill(client)); break + else +#endif + result = (ProcXvPutStill(client)); break; + case xv_GetVideo: result = (ProcXvGetVideo(client)); break; + case xv_GetStill: result = (ProcXvGetStill(client)); break; + case xv_GrabPort: result = (ProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (ProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (ProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (ProcXvSelectPortNotify(client)); break; + case xv_StopVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvStopVideo(client)); break; + else +#endif + result = (ProcXvStopVideo(client)); break; + case xv_SetPortAttribute: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvSetPortAttribute(client)); break; + else +#endif + result = (ProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (ProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (ProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (ProcXvQueryPortAttributes(client)); break; + case xv_PutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutImage(client)); break; + else +#endif + result = (ProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvShmPutImage(client)); break; + else +#endif + result = (ProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (ProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (ProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +int +SProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "SProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (SProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (SProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (SProcXvQueryEncodings(client)); break; + case xv_PutVideo: result = (SProcXvPutVideo(client)); break; + case xv_PutStill: result = (SProcXvPutStill(client)); break; + case xv_GetVideo: result = (SProcXvGetVideo(client)); break; + case xv_GetStill: result = (SProcXvGetStill(client)); break; + case xv_GrabPort: result = (SProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (SProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (SProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (SProcXvSelectPortNotify(client)); break; + case xv_StopVideo: result = (SProcXvStopVideo(client)); break; + case xv_SetPortAttribute: result = (SProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (SProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (SProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (SProcXvQueryPortAttributes(client)); break; + case xv_PutImage: result = (SProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: result = (SProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (SProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (SProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; + +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize; + int na; + XvAdaptorPtr pa; + int nf; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + if(!(pWin = (WindowPtr)LookupWindow(stuff->window, client) )) + { + client->errorValue = stuff->window; + return (BadWindow); + } + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += (strlen(pa->name) + 3) & ~3; + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = totalSize >> 2; + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, ainfo.name_size, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return (client->noClientException); + +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += (strlen(pe->name) + 3) & ~3; + pe++; + } + + rep.length = totalSize >> 2; + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, einfo.name_size, pe->name); + pe++; + } + + return (client->noClientException); + +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvPutStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + register DrawablePtr pDraw; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + if(!(pDraw = (DrawablePtr)LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadWindow); + } + + return XVCALL(diSelectVideoNotify)(client, pDraw, stuff->onoff); + +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diSelectPortNotify)(client, pPort, stuff->onoff); + +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XVCALL(diGrabPort)(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; + +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diUngrabPort)(client, pPort, stuff->time); + +} + + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status; + register DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadDrawable); + } + + return XVCALL(diStopVideo)(client, pPort, pDraw); + +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diSetPortAttribute)(client, pPort, + stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diGetPortAttribute)(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L; + } + + rep.length = (rep.num_attributes * sz_xvAttributeInfo) + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = (size + 3) & ~3L; + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + + + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = (size + 3) >> 2; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, + pImage, (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + if(!(shmdesc = (ShmDescPtr)LookupIDByType(stuff->shmseg, ShmSegType))) + { + client->errorValue = stuff->shmseg; + return BadShmSegCode; + } + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#endif + +#ifdef XvMCExtension +XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id); +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = xalloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, rep.length); + WriteToClient(client, rep.length << 2, (char*)offsets); + + xfree(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = rep.num_formats * sz_xvImageFormatInfo >> 2; + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < rep.num_formats; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + + + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + register char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return ProcXvQueryExtension(client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + register char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcXvQueryAdaptors(client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + register char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryEncodings(client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvGrabPort(client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvUngrabPort(client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + register char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutVideo(client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + register char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutStill(client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + register char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetVideo(client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + register char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetStill(client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvPutImage(client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->offset, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvShmPutImage(client); +} +#endif + + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return ProcXvSelectVideoNotify(client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvSelectPortNotify(client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + register char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return ProcXvStopVideo(client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvSetPortAttribute(client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvGetPortAttribute(client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + register char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvQueryBestSize(client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryPortAttributes(client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->width, n); + return ProcXvQueryImageAttributes(client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + register char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvListImageFormats(client); +} + + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)&rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + register char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + register char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + register char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + register char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + register char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + + + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)&rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)&rep); + + return Success; +} + + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)&rep); + + return Success; +} + + +#ifdef PANORAMIX + + + + +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result = Success, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result = Success, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + + +void XineramifyXv(void) +{ + ScreenPtr pScreen, screen0 = screenInfo.screens[0]; + XvScreenPtr xvsp0 = (XvScreenPtr)screen0->devPrivates[XvScreenIndex].ptr; + XvAdaptorPtr refAdapt, pAdapt; + XvAttributePtr pAttr; + XvScreenPtr xvsp; + Bool isOverlay, hasOverlay; + PanoramiXRes *port; + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k, l; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource); + + if(!xvsp0) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + refAdapt = xvsp0->pAdaptors + i; + + bzero(MatchingAdaptors, sizeof(XvAdaptorPtr) * MAXSCREENS); + + MatchingAdaptors[0] = refAdapt; + + if(!(refAdapt->type & XvInputMask)) continue; + + isOverlay = FALSE; + for(j = 0; j < refAdapt->nAttributes; j++) { + pAttr = refAdapt->pAttributes + j; + if(!strcmp(pAttr->name, "XV_COLORKEY")) { + isOverlay = TRUE; + break; + } + } + + for(j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + xvsp = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* Do not try to go on if xv is not supported on this screen */ + if (xvsp==NULL) continue ; + + /* if the adaptor has the same name it's a perfect match */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if(!strcmp(refAdapt->name, pAdapt->name)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + if(MatchingAdaptors[j]) continue; /* found it */ + + /* otherwise we only look for XvImage adaptors */ + if(!(refAdapt->type & XvImageMask)) continue; + if(refAdapt->nImages <= 0) continue; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + hasOverlay = FALSE; + for(l = 0; l < pAdapt->nAttributes; l++) { + if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + hasOverlay = TRUE; + break; + } + } + if(isOverlay && hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + else if(!isOverlay && !hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + if(MatchingAdaptors[j]) continue; /* found it */ + + /* but we'll take any XvImage pairing if we can get it */ + + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + if(!(port = xalloc(sizeof(PanoramiXRes)))) + break; + port->info[0].id = MatchingAdaptors[0]->base_id + j; + AddResource(port->info[0].id, XvXRTPort, port); + + for(k = 1; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + } + } +} + +#endif + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.NX.original new file mode 100644 index 000000000..f3bfcf58a --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.NX.original @@ -0,0 +1,2277 @@ +#ifdef NXAGENT_UPGRADE + +#if !defined(__sun) && !defined(__CYGWIN__) + +#include "X/NXxvdisp.c" + +#endif + +#else + +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdisp.c,v 1.25 2001/11/18 23:55:48 mvojkovi Exp $ */ + +/* +** File: +** +** xvdisp.c --- Xv server extension dispatch module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include "Xv.h" +#include "Xvproto.h" +#include "xvdix.h" +#ifdef MITSHM +#define _XSHM_SERVER_ +#include "shmstr.h" +#endif + +#include "Trap.h" + +#undef TEST +#undef DEBUG + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; + +#ifdef MITSHM +static int XineramaXvShmPutImage(ClientPtr); +#endif +static int XineramaXvPutImage(ClientPtr); +static int XineramaXvPutVideo(ClientPtr); +static int XineramaXvPutStill(ClientPtr); +static int XineramaXvSetPortAttribute(ClientPtr); +static int XineramaXvStopVideo(ClientPtr); +#endif + +/* INTERNAL */ + +static int ProcXvQueryExtension(ClientPtr); +static int ProcXvQueryAdaptors(ClientPtr); +static int ProcXvQueryEncodings(ClientPtr); +static int ProcXvPutVideo(ClientPtr); +static int ProcXvPutStill(ClientPtr); +static int ProcXvGetVideo(ClientPtr); +static int ProcXvGetStill(ClientPtr); +static int ProcXvGrabPort(ClientPtr); +static int ProcXvUngrabPort(ClientPtr); +static int ProcXvSelectVideoNotify(ClientPtr); +static int ProcXvSelectPortNotify(ClientPtr); +static int ProcXvStopVideo(ClientPtr); +static int ProcXvSetPortAttribute(ClientPtr); +static int ProcXvGetPortAttribute(ClientPtr); +static int ProcXvQueryBestSize(ClientPtr); +static int ProcXvQueryPortAttributes(ClientPtr); +static int ProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int ProcXvShmPutImage(ClientPtr); +#endif +static int ProcXvQueryImageAttributes(ClientPtr); +static int ProcXvListImageFormats(ClientPtr); + +static int SProcXvQueryExtension(ClientPtr); +static int SProcXvQueryAdaptors(ClientPtr); +static int SProcXvQueryEncodings(ClientPtr); +static int SProcXvPutVideo(ClientPtr); +static int SProcXvPutStill(ClientPtr); +static int SProcXvGetVideo(ClientPtr); +static int SProcXvGetStill(ClientPtr); +static int SProcXvGrabPort(ClientPtr); +static int SProcXvUngrabPort(ClientPtr); +static int SProcXvSelectVideoNotify(ClientPtr); +static int SProcXvSelectPortNotify(ClientPtr); +static int SProcXvStopVideo(ClientPtr); +static int SProcXvSetPortAttribute(ClientPtr); +static int SProcXvGetPortAttribute(ClientPtr); +static int SProcXvQueryBestSize(ClientPtr); +static int SProcXvQueryPortAttributes(ClientPtr); +static int SProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int SProcXvShmPutImage(ClientPtr); +#endif +static int SProcXvQueryImageAttributes(ClientPtr); +static int SProcXvListImageFormats(ClientPtr); + +static int SWriteQueryAdaptorsReply(ClientPtr, xvQueryAdaptorsReply *); +static int SWriteQueryExtensionReply(ClientPtr, xvQueryExtensionReply *); +static int SWriteQueryEncodingsReply(ClientPtr, xvQueryEncodingsReply *); +static int SWriteAdaptorInfo(ClientPtr, xvAdaptorInfo *); +static int SWriteEncodingInfo(ClientPtr, xvEncodingInfo *); +static int SWriteFormat(ClientPtr, xvFormat *); +static int SWriteAttributeInfo(ClientPtr, xvAttributeInfo *); +static int SWriteGrabPortReply(ClientPtr, xvGrabPortReply *); +static int SWriteGetPortAttributeReply(ClientPtr, xvGetPortAttributeReply *); +static int SWriteQueryBestSizeReply(ClientPtr, xvQueryBestSizeReply *); +static int SWriteQueryPortAttributesReply( + ClientPtr, xvQueryPortAttributesReply *); +static int SWriteQueryImageAttributesReply( + ClientPtr, xvQueryImageAttributesReply*); +static int SWriteListImageFormatsReply(ClientPtr, xvListImageFormatsReply*); +static int SWriteImageFormatInfo(ClientPtr, xvImageFormatInfo*); + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +/* +** ProcXvDispatch +** +** +** +*/ + +int +ProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (ProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (ProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (ProcXvQueryEncodings(client)); break; + case xv_PutVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutVideo(client)); break; + else +#endif + result = (ProcXvPutVideo(client)); break; + case xv_PutStill: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutStill(client)); break + else +#endif + result = (ProcXvPutStill(client)); break; + case xv_GetVideo: result = (ProcXvGetVideo(client)); break; + case xv_GetStill: result = (ProcXvGetStill(client)); break; + case xv_GrabPort: result = (ProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (ProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (ProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (ProcXvSelectPortNotify(client)); break; + case xv_StopVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvStopVideo(client)); break; + else +#endif + result = (ProcXvStopVideo(client)); break; + case xv_SetPortAttribute: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvSetPortAttribute(client)); break; + else +#endif + result = (ProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (ProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (ProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (ProcXvQueryPortAttributes(client)); break; + case xv_PutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutImage(client)); break; + else +#endif + result = (ProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvShmPutImage(client)); break; + else +#endif + result = (ProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (ProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (ProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +int +SProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "SProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (SProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (SProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (SProcXvQueryEncodings(client)); break; + case xv_PutVideo: result = (SProcXvPutVideo(client)); break; + case xv_PutStill: result = (SProcXvPutStill(client)); break; + case xv_GetVideo: result = (SProcXvGetVideo(client)); break; + case xv_GetStill: result = (SProcXvGetStill(client)); break; + case xv_GrabPort: result = (SProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (SProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (SProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (SProcXvSelectPortNotify(client)); break; + case xv_StopVideo: result = (SProcXvStopVideo(client)); break; + case xv_SetPortAttribute: result = (SProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (SProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (SProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (SProcXvQueryPortAttributes(client)); break; + case xv_PutImage: result = (SProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: result = (SProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (SProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (SProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; + +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize; + int na; + XvAdaptorPtr pa; + int nf; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + if(!(pWin = (WindowPtr)LookupWindow(stuff->window, client) )) + { + client->errorValue = stuff->window; + return (BadWindow); + } + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += (strlen(pa->name) + 3) & ~3; + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = totalSize >> 2; + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, ainfo.name_size, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return (client->noClientException); + +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += (strlen(pe->name) + 3) & ~3; + pe++; + } + + rep.length = totalSize >> 2; + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, einfo.name_size, pe->name); + pe++; + } + + return (client->noClientException); + +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvPutStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + register DrawablePtr pDraw; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + if(!(pDraw = (DrawablePtr)LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadWindow); + } + + return XVCALL(diSelectVideoNotify)(client, pDraw, stuff->onoff); + +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diSelectPortNotify)(client, pPort, stuff->onoff); + +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XVCALL(diGrabPort)(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; + +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diUngrabPort)(client, pPort, stuff->time); + +} + + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status; + register DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadDrawable); + } + + return XVCALL(diStopVideo)(client, pPort, pDraw); + +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diSetPortAttribute)(client, pPort, + stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diGetPortAttribute)(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L; + } + + rep.length = (rep.num_attributes * sz_xvAttributeInfo) + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = (size + 3) & ~3L; + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + + + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = (size + 3) >> 2; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, + pImage, (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + if(!(shmdesc = (ShmDescPtr)LookupIDByType(stuff->shmseg, ShmSegType))) + { + client->errorValue = stuff->shmseg; + return BadShmSegCode; + } + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#endif + +#ifdef XvMCExtension +XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id); +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = xalloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, rep.length); + WriteToClient(client, rep.length << 2, (char*)offsets); + + xfree(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = rep.num_formats * sz_xvImageFormatInfo >> 2; + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < rep.num_formats; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + + + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + register char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return ProcXvQueryExtension(client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + register char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcXvQueryAdaptors(client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + register char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryEncodings(client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvGrabPort(client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvUngrabPort(client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + register char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutVideo(client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + register char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutStill(client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + register char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetVideo(client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + register char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetStill(client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvPutImage(client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->offset, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvShmPutImage(client); +} +#endif + + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return ProcXvSelectVideoNotify(client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvSelectPortNotify(client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + register char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return ProcXvStopVideo(client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvSetPortAttribute(client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvGetPortAttribute(client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + register char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvQueryBestSize(client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryPortAttributes(client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->width, n); + return ProcXvQueryImageAttributes(client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + register char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvListImageFormats(client); +} + + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)&rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + register char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + register char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + register char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + register char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + register char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + + + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)&rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)&rep); + + return Success; +} + + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)&rep); + + return Success; +} + + +#ifdef PANORAMIX + + + + +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result = Success, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result = Success, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + + +void XineramifyXv(void) +{ + ScreenPtr pScreen, screen0 = screenInfo.screens[0]; + XvScreenPtr xvsp0 = (XvScreenPtr)screen0->devPrivates[XvScreenIndex].ptr; + XvAdaptorPtr refAdapt, pAdapt; + XvAttributePtr pAttr; + XvScreenPtr xvsp; + Bool isOverlay, hasOverlay; + PanoramiXRes *port; + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k, l; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource); + + if(!xvsp0) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + refAdapt = xvsp0->pAdaptors + i; + + bzero(MatchingAdaptors, sizeof(XvAdaptorPtr) * MAXSCREENS); + + MatchingAdaptors[0] = refAdapt; + + if(!(refAdapt->type & XvInputMask)) continue; + + isOverlay = FALSE; + for(j = 0; j < refAdapt->nAttributes; j++) { + pAttr = refAdapt->pAttributes + j; + if(!strcmp(pAttr->name, "XV_COLORKEY")) { + isOverlay = TRUE; + break; + } + } + + for(j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + xvsp = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* Do not try to go on if xv is not supported on this screen */ + if (xvsp==NULL) continue ; + + /* if the adaptor has the same name it's a perfect match */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if(!strcmp(refAdapt->name, pAdapt->name)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + if(MatchingAdaptors[j]) continue; /* found it */ + + /* otherwise we only look for XvImage adaptors */ + if(!(refAdapt->type & XvImageMask)) continue; + if(refAdapt->nImages <= 0) continue; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + hasOverlay = FALSE; + for(l = 0; l < pAdapt->nAttributes; l++) { + if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + hasOverlay = TRUE; + break; + } + } + if(isOverlay && hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + else if(!isOverlay && !hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + if(MatchingAdaptors[j]) continue; /* found it */ + + /* but we'll take any XvImage pairing if we can get it */ + + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + if(!(port = xalloc(sizeof(PanoramiXRes)))) + break; + port->info[0].id = MatchingAdaptors[0]->base_id + j; + AddResource(port->info[0].id, XvXRTPort, port); + + for(k = 1; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + } + } +} + +#endif + +#endif /* #ifdef NXAGENT_UPGRADE */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.XF86.original b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.XF86.original new file mode 100644 index 000000000..3d321e8ae --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.XF86.original @@ -0,0 +1,2214 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdisp.c,v 1.25 2001/11/18 23:55:48 mvojkovi Exp $ */ + +/* +** File: +** +** xvdisp.c --- Xv server extension dispatch module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include "Xv.h" +#include "Xvproto.h" +#include "xvdix.h" +#ifdef MITSHM +#define _XSHM_SERVER_ +#include "shmstr.h" +#endif + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; + +#ifdef MITSHM +static int XineramaXvShmPutImage(ClientPtr); +#endif +static int XineramaXvPutImage(ClientPtr); +static int XineramaXvPutVideo(ClientPtr); +static int XineramaXvPutStill(ClientPtr); +static int XineramaXvSetPortAttribute(ClientPtr); +static int XineramaXvStopVideo(ClientPtr); +#endif + +/* INTERNAL */ + +static int ProcXvQueryExtension(ClientPtr); +static int ProcXvQueryAdaptors(ClientPtr); +static int ProcXvQueryEncodings(ClientPtr); +static int ProcXvPutVideo(ClientPtr); +static int ProcXvPutStill(ClientPtr); +static int ProcXvGetVideo(ClientPtr); +static int ProcXvGetStill(ClientPtr); +static int ProcXvGrabPort(ClientPtr); +static int ProcXvUngrabPort(ClientPtr); +static int ProcXvSelectVideoNotify(ClientPtr); +static int ProcXvSelectPortNotify(ClientPtr); +static int ProcXvStopVideo(ClientPtr); +static int ProcXvSetPortAttribute(ClientPtr); +static int ProcXvGetPortAttribute(ClientPtr); +static int ProcXvQueryBestSize(ClientPtr); +static int ProcXvQueryPortAttributes(ClientPtr); +static int ProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int ProcXvShmPutImage(ClientPtr); +#endif +static int ProcXvQueryImageAttributes(ClientPtr); +static int ProcXvListImageFormats(ClientPtr); + +static int SProcXvQueryExtension(ClientPtr); +static int SProcXvQueryAdaptors(ClientPtr); +static int SProcXvQueryEncodings(ClientPtr); +static int SProcXvPutVideo(ClientPtr); +static int SProcXvPutStill(ClientPtr); +static int SProcXvGetVideo(ClientPtr); +static int SProcXvGetStill(ClientPtr); +static int SProcXvGrabPort(ClientPtr); +static int SProcXvUngrabPort(ClientPtr); +static int SProcXvSelectVideoNotify(ClientPtr); +static int SProcXvSelectPortNotify(ClientPtr); +static int SProcXvStopVideo(ClientPtr); +static int SProcXvSetPortAttribute(ClientPtr); +static int SProcXvGetPortAttribute(ClientPtr); +static int SProcXvQueryBestSize(ClientPtr); +static int SProcXvQueryPortAttributes(ClientPtr); +static int SProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int SProcXvShmPutImage(ClientPtr); +#endif +static int SProcXvQueryImageAttributes(ClientPtr); +static int SProcXvListImageFormats(ClientPtr); + +static int SWriteQueryAdaptorsReply(ClientPtr, xvQueryAdaptorsReply *); +static int SWriteQueryExtensionReply(ClientPtr, xvQueryExtensionReply *); +static int SWriteQueryEncodingsReply(ClientPtr, xvQueryEncodingsReply *); +static int SWriteAdaptorInfo(ClientPtr, xvAdaptorInfo *); +static int SWriteEncodingInfo(ClientPtr, xvEncodingInfo *); +static int SWriteFormat(ClientPtr, xvFormat *); +static int SWriteAttributeInfo(ClientPtr, xvAttributeInfo *); +static int SWriteGrabPortReply(ClientPtr, xvGrabPortReply *); +static int SWriteGetPortAttributeReply(ClientPtr, xvGetPortAttributeReply *); +static int SWriteQueryBestSizeReply(ClientPtr, xvQueryBestSizeReply *); +static int SWriteQueryPortAttributesReply( + ClientPtr, xvQueryPortAttributesReply *); +static int SWriteQueryImageAttributesReply( + ClientPtr, xvQueryImageAttributesReply*); +static int SWriteListImageFormatsReply(ClientPtr, xvListImageFormatsReply*); +static int SWriteImageFormatInfo(ClientPtr, xvImageFormatInfo*); + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +/* +** ProcXvDispatch +** +** +** +*/ + +int +ProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + switch (stuff->data) + { + case xv_QueryExtension: return(ProcXvQueryExtension(client)); + case xv_QueryAdaptors: return(ProcXvQueryAdaptors(client)); + case xv_QueryEncodings: return(ProcXvQueryEncodings(client)); + case xv_PutVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutVideo(client)); + else +#endif + return(ProcXvPutVideo(client)); + case xv_PutStill: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutStill(client)); + else +#endif + return(ProcXvPutStill(client)); + case xv_GetVideo: return(ProcXvGetVideo(client)); + case xv_GetStill: return(ProcXvGetStill(client)); + case xv_GrabPort: return(ProcXvGrabPort(client)); + case xv_UngrabPort: return(ProcXvUngrabPort(client)); + case xv_SelectVideoNotify: return(ProcXvSelectVideoNotify(client)); + case xv_SelectPortNotify: return(ProcXvSelectPortNotify(client)); + case xv_StopVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvStopVideo(client)); + else +#endif + return(ProcXvStopVideo(client)); + case xv_SetPortAttribute: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvSetPortAttribute(client)); + else +#endif + return(ProcXvSetPortAttribute(client)); + case xv_GetPortAttribute: return(ProcXvGetPortAttribute(client)); + case xv_QueryBestSize: return(ProcXvQueryBestSize(client)); + case xv_QueryPortAttributes: return(ProcXvQueryPortAttributes(client)); + case xv_PutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutImage(client)); + else +#endif + return(ProcXvPutImage(client)); +#ifdef MITSHM + case xv_ShmPutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvShmPutImage(client)); + else +#endif + return(ProcXvShmPutImage(client)); +#endif + case xv_QueryImageAttributes: return(ProcXvQueryImageAttributes(client)); + case xv_ListImageFormats: return(ProcXvListImageFormats(client)); + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + return(BadImplementation); + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + } +} + +int +SProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + switch (stuff->data) + { + case xv_QueryExtension: return(SProcXvQueryExtension(client)); + case xv_QueryAdaptors: return(SProcXvQueryAdaptors(client)); + case xv_QueryEncodings: return(SProcXvQueryEncodings(client)); + case xv_PutVideo: return(SProcXvPutVideo(client)); + case xv_PutStill: return(SProcXvPutStill(client)); + case xv_GetVideo: return(SProcXvGetVideo(client)); + case xv_GetStill: return(SProcXvGetStill(client)); + case xv_GrabPort: return(SProcXvGrabPort(client)); + case xv_UngrabPort: return(SProcXvUngrabPort(client)); + case xv_SelectVideoNotify: return(SProcXvSelectVideoNotify(client)); + case xv_SelectPortNotify: return(SProcXvSelectPortNotify(client)); + case xv_StopVideo: return(SProcXvStopVideo(client)); + case xv_SetPortAttribute: return(SProcXvSetPortAttribute(client)); + case xv_GetPortAttribute: return(SProcXvGetPortAttribute(client)); + case xv_QueryBestSize: return(SProcXvQueryBestSize(client)); + case xv_QueryPortAttributes: return(SProcXvQueryPortAttributes(client)); + case xv_PutImage: return(SProcXvPutImage(client)); +#ifdef MITSHM + case xv_ShmPutImage: return(SProcXvShmPutImage(client)); +#endif + case xv_QueryImageAttributes: return(SProcXvQueryImageAttributes(client)); + case xv_ListImageFormats: return(SProcXvListImageFormats(client)); + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + return(BadImplementation); + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + } +} + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; + +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize; + int na; + XvAdaptorPtr pa; + int nf; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + if(!(pWin = (WindowPtr)LookupWindow(stuff->window, client) )) + { + client->errorValue = stuff->window; + return (BadWindow); + } + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += (strlen(pa->name) + 3) & ~3; + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = totalSize >> 2; + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, ainfo.name_size, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return (client->noClientException); + +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += (strlen(pe->name) + 3) & ~3; + pe++; + } + + rep.length = totalSize >> 2; + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, einfo.name_size, pe->name); + pe++; + } + + return (client->noClientException); + +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvPutStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + register DrawablePtr pDraw; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + if(!(pDraw = (DrawablePtr)LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadWindow); + } + + return XVCALL(diSelectVideoNotify)(client, pDraw, stuff->onoff); + +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diSelectPortNotify)(client, pPort, stuff->onoff); + +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XVCALL(diGrabPort)(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; + +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diUngrabPort)(client, pPort, stuff->time); + +} + + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status; + register DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadDrawable); + } + + return XVCALL(diStopVideo)(client, pPort, pDraw); + +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diSetPortAttribute)(client, pPort, + stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diGetPortAttribute)(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L; + } + + rep.length = (rep.num_attributes * sz_xvAttributeInfo) + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = (size + 3) & ~3L; + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + + + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = (size + 3) >> 2; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, + pImage, (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + if(!(shmdesc = (ShmDescPtr)LookupIDByType(stuff->shmseg, ShmSegType))) + { + client->errorValue = stuff->shmseg; + return BadShmSegCode; + } + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#endif + +#ifdef XvMCExtension +XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id); +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = xalloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, rep.length); + WriteToClient(client, rep.length << 2, (char*)offsets); + + xfree(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = rep.num_formats * sz_xvImageFormatInfo >> 2; + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < rep.num_formats; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + + + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + register char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return ProcXvQueryExtension(client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + register char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcXvQueryAdaptors(client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + register char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryEncodings(client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvGrabPort(client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvUngrabPort(client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + register char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutVideo(client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + register char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutStill(client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + register char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetVideo(client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + register char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetStill(client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvPutImage(client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->offset, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvShmPutImage(client); +} +#endif + + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return ProcXvSelectVideoNotify(client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvSelectPortNotify(client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + register char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return ProcXvStopVideo(client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvSetPortAttribute(client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvGetPortAttribute(client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + register char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvQueryBestSize(client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryPortAttributes(client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->width, n); + return ProcXvQueryImageAttributes(client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + register char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvListImageFormats(client); +} + + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)&rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + register char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + register char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + register char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + register char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + register char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + + + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)&rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)&rep); + + return Success; +} + + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)&rep); + + return Success; +} + + +#ifdef PANORAMIX + + + + +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result = Success, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result = Success, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && + (stuff->drawable == WindowTable[0]->drawable.id); + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + + +void XineramifyXv(void) +{ + ScreenPtr pScreen, screen0 = screenInfo.screens[0]; + XvScreenPtr xvsp0 = (XvScreenPtr)screen0->devPrivates[XvScreenIndex].ptr; + XvAdaptorPtr refAdapt, pAdapt; + XvAttributePtr pAttr; + XvScreenPtr xvsp; + Bool isOverlay, hasOverlay; + PanoramiXRes *port; + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k, l; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource); + + if(!xvsp0) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + refAdapt = xvsp0->pAdaptors + i; + + bzero(MatchingAdaptors, sizeof(XvAdaptorPtr) * MAXSCREENS); + + MatchingAdaptors[0] = refAdapt; + + if(!(refAdapt->type & XvInputMask)) continue; + + isOverlay = FALSE; + for(j = 0; j < refAdapt->nAttributes; j++) { + pAttr = refAdapt->pAttributes + j; + if(!strcmp(pAttr->name, "XV_COLORKEY")) { + isOverlay = TRUE; + break; + } + } + + for(j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + xvsp = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* Do not try to go on if xv is not supported on this screen */ + if (xvsp==NULL) continue ; + + /* if the adaptor has the same name it's a perfect match */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if(!strcmp(refAdapt->name, pAdapt->name)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + if(MatchingAdaptors[j]) continue; /* found it */ + + /* otherwise we only look for XvImage adaptors */ + if(!(refAdapt->type & XvImageMask)) continue; + if(refAdapt->nImages <= 0) continue; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + hasOverlay = FALSE; + for(l = 0; l < pAdapt->nAttributes; l++) { + if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + hasOverlay = TRUE; + break; + } + } + if(isOverlay && hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + else if(!isOverlay && !hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + if(MatchingAdaptors[j]) continue; /* found it */ + + /* but we'll take any XvImage pairing if we can get it */ + + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + if(!(port = xalloc(sizeof(PanoramiXRes)))) + break; + port->info[0].id = MatchingAdaptors[0]->base_id + j; + AddResource(port->info[0].id, XvXRTPort, port); + + for(k = 1; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + } + } +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.c b/nx-X11/programs/Xserver/hw/nxagent/Options.c new file mode 100644 index 000000000..3a27e0da0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Options.c @@ -0,0 +1,178 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include +#include + +#include "X.h" + +#include "Agent.h" +#include "Args.h" +#include "Options.h" +#include "Utils.h" + +/* + * Instead of having a single options repository + * data could be attached to the display or the + * screen. The macro nxagentOption() should make + * the transition simple. + */ + +AgentOptionsRec nxagentOptions; + +AgentOptionsRec nxagentOptionsBackup; + +AgentOptionsPtr nxagentOptionsPtr = &nxagentOptions; + +/* + * This must be called at startup to initialize + * the options repository to the default values. + */ + +void nxagentInitOptions() +{ + nxagentOptions.LinkType = UNDEFINED; + + nxagentOptions.Desktop = UNDEFINED; + nxagentOptions.Persistent = 1; + nxagentOptions.Rootless = UNDEFINED; + nxagentOptions.Fullscreen = UNDEFINED; + + nxagentOptions.X = 0; + nxagentOptions.Y = 0; + nxagentOptions.Width = 0; + nxagentOptions.Height = 0; + nxagentOptions.BorderWidth = 0; + + nxagentOptions.SavedX = 0; + nxagentOptions.SavedY = 0; + nxagentOptions.SavedWidth = 0; + nxagentOptions.SavedHeight = 0; + + nxagentOptions.Timeout = 0; + + nxagentOptions.Nested = 0; + + nxagentOptions.BackingStore = BackingStoreUndefined; + + nxagentOptions.Clipboard = ClipboardBoth; + + nxagentOptions.SharedMemory = 1; + + nxagentOptions.SharedPixmaps = 1; + + nxagentOptions.DeviceControl = 0; + + nxagentOptions.ResetKeyboardAtResume = 1; + + nxagentOptions.Reset = 0; + + nxagentOptions.RootX = 0; + nxagentOptions.RootY = 0; + nxagentOptions.RootWidth = 0; + nxagentOptions.RootHeight = 0; + + nxagentOptions.ViewportXSpan = 0; + nxagentOptions.ViewportYSpan = 0; + + #ifndef __CYGWIN32__ + + nxagentOptions.DesktopResize = 1; + + #else + + nxagentOptions.DesktopResize = 0; + + #endif + + nxagentOptions.Ratio = DONT_SCALE; + nxagentOptions.XRatio = DONT_SCALE; + nxagentOptions.YRatio = DONT_SCALE; + + nxagentOptions.FloatRatio = 1.0; + nxagentOptions.FloatXRatio = 1.0; + nxagentOptions.FloatYRatio = 1.0; + + nxagentOptions.UseDamage = 1; + + nxagentOptions.Binder = UNDEFINED; + nxagentOptions.BinderOptions = NULL; + + nxagentOptions.Xdmcp = 0; + + nxagentOptions.DisplayLatency = 0; + nxagentOptions.DisplayBuffer = UNDEFINED; + nxagentOptions.DisplayCoalescence = 0; + + nxagentOptions.Composite = 1; + + nxagentOptions.IgnoreVisibility = 0; + + nxagentOptions.ViewOnly = 0; + + nxagentOptions.Adaptive = 0; + + nxagentOptions.Streaming = 0; + + nxagentOptions.DeferLevel = UNDEFINED; + nxagentOptions.DeferTimeout = 200; + + nxagentOptions.TileWidth = UNDEFINED; + nxagentOptions.TileHeight = UNDEFINED; + + nxagentOptions.Menu = 1; + + nxagentOptions.ClientOs = UNDEFINED; + + nxagentOptions.InhibitXkb = 1; +} + +/* + * This is called at session reconnection + * to reset some options to their default + * values. The reason to avoid calling the + * nxagentInitOptions() is that not all the + * options can change value when reconnec- + * ting. + */ + +void nxagentResetOptions() +{ + if (nxagentLockDeferLevel == 0) + { + nxagentOptions.DeferLevel = UNDEFINED; + } + + nxagentOptions.DeferTimeout = 200; + + nxagentOptions.TileWidth = UNDEFINED; + nxagentOptions.TileHeight = UNDEFINED; +} + +void nxagentSaveOptions() +{ + memcpy(&nxagentOptionsBackup, &nxagentOptions, sizeof(AgentOptionsRec)); +} + +void nxagentRestoreOptions() +{ + nxagentOptions.DeferLevel = nxagentOptionsBackup.DeferLevel; + nxagentOptions.DeferTimeout = nxagentOptionsBackup.DeferTimeout; + + nxagentOptions.TileWidth = nxagentOptionsBackup.TileWidth; + nxagentOptions.TileHeight = nxagentOptionsBackup.TileHeight; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.h b/nx-X11/programs/Xserver/hw/nxagent/Options.h new file mode 100644 index 000000000..493ba6f61 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Options.h @@ -0,0 +1,397 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Options_H__ +#define __Options_H__ + +#ifndef True +#define True 1 +#endif + +#ifndef False +#define False 0 +#endif + +#define UNDEFINED -1 + +typedef enum _BackingStoreMode +{ + BackingStoreUndefined = -1, + BackingStoreNever, + BackingStoreWhenRequested, + BackingStoreForce + +} BackingStoreMode; + +typedef enum _ClipboardMode +{ + ClipboardBoth, + ClipboardClient, + ClipboardServer, + ClipboardNone + +} ClipboardMode; + +typedef enum _ClientOsType +{ + ClientOsWinnt = 0, + ClientOsLinux, + ClientOsSolaris, + ClientOsMac + +} ClientOsType; + +/* + * Set of options affecting agent operations. + */ + +typedef struct _AgentOptions +{ + /* + * Link type of the NX connection or none, + * if this is a direct X11 connection. + */ + + int LinkType; + + /* + * Is agent running in desktop mode? This + * is presently the default. + */ + + int Desktop; + + /* + * True if user activated rootless mode. + */ + + int Rootless; + + /* + * True for shadow mode. + */ + + int Shadow; + + /* + * True if user activated persistent mode. + */ + + int Persistent; + + /* + * True if user activated fullscreen mode. + */ + + int Fullscreen; + + /* + * Set to the auto-disconnect timeout, if + * the user activated this feature. + */ + + int Timeout; + + /* + * Geometry of the agent's window. + */ + + int X; + int Y; + int Width; + int Height; + int BorderWidth; + + /* + * Geometry of the agent's window in window + * mode. Used to restore window size when + * switching back to window mode from full- + * screen. + */ + + int SavedX; + int SavedY; + int SavedWidth; + int SavedHeight; + + int SavedRootWidth; + int SavedRootHeight; + + /* + * Set if agent is running nested in another + * agent X server. + */ + + int Nested; + + /* + * Selected backing-store mode. + */ + + BackingStoreMode BackingStore; + + /* + * Selected clipboard mode. + */ + + ClipboardMode Clipboard; + + /* + * Enable agent to use the MITSHM extension in + * path from remote proxy to the real X server. + */ + + int SharedMemory; + + /* + * Enable agent to use shared Pixmaps + */ + + int SharedPixmaps; + + /* + * Enable agent to propagate keyboard and pointer + * device configuration to the remote X server. + */ + + int DeviceControl; + + /* + * Resuming keyboard device corrects keymap if session + * migrates across platforms with different keycode + * layout. + */ + + int ResetKeyboardAtResume; + + /* + * Reset server when the last client disconnects. + */ + + int Reset; + + /* + * Geometry of the agent root window, relative to + * the agent default window. + */ + + int RootX; + int RootY; + int RootWidth; + int RootHeight; + + /* + * Horizontal and vertical span of the + * agent viewport. + */ + + int ViewportXSpan; + int ViewportYSpan; + + /* + * True if the user can resize the desktop + * by dragging the window border. + */ + + int DesktopResize; + + /* + * The scaling ratio of the shadow agent. + */ + + int Ratio; + + int XRatio; + + int YRatio; + + float FloatRatio; + + float FloatXRatio; + + float FloatYRatio; + + /* + * The shadow agent uses the Damage extension. + */ + + int UseDamage; + + /* + * Was the agent run with the -B option? + */ + + int Binder; + + char *BinderOptions; + + /* + * Set if the agent has to connect to a + * desktop manager to start the session. + */ + + int Xdmcp; + + /* + * Latency of the link. It is simply set + * to a reference value, calculated based + * on the time required to complete the + * query of the agent's atoms at session + * startup. + */ + + int DisplayLatency; + + /* + * Size of the Xlib display buffer. The + * default is set according to the link + * type. + */ + + int DisplayBuffer; + + /* + * Buffer coalescence timeout. + */ + + int DisplayCoalescence; + + /* + * Use the composite extension when + * available on the remote display. + */ + + int Composite; + + /* + * If set, don't skip internal operations + * when the agent window is not fully visible. + */ + + int IgnoreVisibility; + + /* + * If set, prevent the shadow session to + * interact with master diplay. + */ + + int ViewOnly; + + /* + * If true select a lossy or lossless comp- + * ression method based on the characterist- + * ics of the image. + */ + + int Adaptive; + + /* + * Stream the images and update the display + * when the image has been completely trans- + * ferred. + */ + + int Streaming; + + /* + * Use a lazy approach in updating the remote + * display. This means delaying the bandwidth + * consuming graphic operations and synchroniz- + * ing the screen at idle time. + */ + + int DeferLevel; + + /* + * Maxuimum elapsed time before a new full + * synchronization. + */ + + unsigned long DeferTimeout; + + /* + * Maximum size of the tile used when sending + * an image to the remote display. + */ + + int TileWidth; + int TileHeight; + + /* + * Enabling/disabling the pulldown menu. + */ + + int Menu; + + /* + * Specify the Operative System of the client. + */ + + int ClientOs; + + /* + * Inhibit some XKEYBOARD requests. + */ + + int InhibitXkb; + +} AgentOptionsRec; + +typedef AgentOptionsRec *AgentOptionsPtr; + +extern AgentOptionsPtr nxagentOptionsPtr; + +/* + * Macros and functions giving access to options. + */ + +#define nxagentOption(option) \ + (nxagentOptionsPtr -> option) + +#define nxagentChangeOption(option, value) \ + (nxagentOptionsPtr -> option = (value)) + +#define nxagentOptions() \ + (nxagentOptionsPtr) + +/* + * Initialize the options to the default values. + */ + +extern void nxagentInitOptions(void); + +/* + * Initialize some options to the default values + * at reconnection. + */ + +extern void nxagentResetOptions(void); + +/* + * Save a copy of the current option repository. + */ + +extern void nxagentSaveOptions(void); + +/* + * Restore the options reset by nxagentResetOptions + * to their backup value. + */ + +extern void nxagentRestoreOptions(void); + +#endif /* __Options_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixels.c b/nx-X11/programs/Xserver/hw/nxagent/Pixels.c new file mode 100644 index 000000000..03970a14f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Pixels.c @@ -0,0 +1,384 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include +#include + +#include "Xmd.h" +#include "Xlib.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#define PIXEL_ELEMENTS 256 +#define PIXEL_THRESHOLD 8 +#define PIXEL_STEP 7 + +unsigned int Get16(const char *buffer, int order); +unsigned int Get24(const char *buffer, int order); +unsigned int Get32(const char *buffer, int order); + +void Put16(unsigned int value, char *buffer, int order); +void Put24(unsigned int value, char *buffer, int order); +void Put32(unsigned int value, char *buffer, int order); + +static int nxagentComparePixels(const void *p1, const void *p2) +{ + int pixel1 = *((int *) p1); + int pixel2 = *((int *) p2); + + return (pixel1 < pixel2 ? -1 : (pixel1 == pixel2 ? 0 : 1)); +} + +int nxagentUniquePixels(XImage *image) +{ + int i = 0; + + int pixels[PIXEL_ELEMENTS]; + + int elements = PIXEL_ELEMENTS; + int unique = 0; + + int total; + int ratio; + int step; + + int last = -1; + + const char *next = image -> data; + + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Image geometry [%d,%d] depth [%d] bits per pixel [%d].\n", + image -> width, image -> height, image -> depth, image -> bits_per_pixel); + #endif + + /* + * Take at most 256 pixels from the image. + */ + + total = image -> width * image -> height; + + step = total / elements; + + if (step < PIXEL_STEP) + { + step = PIXEL_STEP; + } + + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Step is [%d] with [%d] pixels and [%d] elements.\n", + step, total, elements); + #endif + + /* + * Shift at the left after each scanline. + */ + + if (image -> bytes_per_line % step == 0) + { + step++; + + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Increasing step to [%d] with [%d] bytes per line.\n", + step, image -> bytes_per_line); + #endif + } + + elements = total / step; + + if (elements > PIXEL_ELEMENTS) + { + elements = PIXEL_ELEMENTS; + } + + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Step is now [%d] with [%d] elements.\n", + step, elements); + #endif + + if (elements < PIXEL_THRESHOLD) + { + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Assuming ratio [100] with only [%d] elements.\n", + elements); + #endif + + return 100; + } + + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Scanning [%d] pixels out of [%d] with step [%d].\n", + elements, total, step); + #endif + + /* + * Take one pixel every n from the image and + * add it to the array. + */ + + switch (image -> bits_per_pixel) + { + case 32: + { + for (i = 0; i < elements; i++) + { + pixels[i] = Get32(next, image -> byte_order); + + next += (4 * step); + + #ifdef DEBUG + fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n", + i, pixels[i]); + #endif + } + + break; + } + case 24: + { + for (i = 0; i < elements; i++) + { + pixels[i] = Get24(next, image -> byte_order); + + next += (3 * step); + + #ifdef DEBUG + fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n", + i, pixels[i]); + #endif + } + + break; + } + case 16: + case 15: + { + /* + * Note that the padding bytes at the end + * of the scanline are included in the set. + * This is not a big problem. What we want + * to find out is just how compressible is + * the image data. + */ + + for (i = 0; i < elements; i++) + { + pixels[i] = Get16(next, image -> byte_order); + + next += (2 * step); + + #ifdef DEBUG + fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n", + i, pixels[i]); + #endif + } + + break; + } + default: + { + #ifdef PANIC + fprintf(stderr, "nxagentUniquePixels: PANIC! Assuming ratio [100] with [%d] bits per pixel.\n", + image -> bits_per_pixel); + #endif + + return 100; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Sorting [%d] elements in the list.\n", i); + #endif + + qsort(pixels, elements, sizeof(int), nxagentComparePixels); + + for (i = 0; i < elements; i++) + { + if (last != pixels[i]) + { + unique++; + + last = pixels[i]; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n", + i, pixels[i]); + #endif + } + + ratio = unique * 100 / elements; + + #ifdef TEST + fprintf(stderr, "nxagentUniquePixels: Found [%d] unique pixels out of [%d] with ratio [%d%%].\n", + unique, elements, ratio); + #endif + + return ratio; +} + +unsigned int Get16(const char *buffer, int order) +{ + unsigned int result; + + if (order == MSBFirst) + { + result = *buffer; + + result <<= 8; + + result += buffer[1]; + } + else + { + result = buffer[1]; + + result <<= 8; + + result += *buffer; + } + + return result; +} + +unsigned int Get24(const char *buffer, int order) +{ + int i; + + const char *next = (order == MSBFirst ? buffer : buffer + 2); + + unsigned int result = 0; + + for (i = 0; i < 3; i++) + { + result <<= 8; + + result += *next; + + if (order == MSBFirst) + { + next++; + } + else + { + next--; + } + } + + return result; +} + +unsigned int Get32(const char *buffer, int order) +{ + int i; + + const char *next = (order == MSBFirst ? buffer : buffer + 3); + + unsigned int result = 0; + + for (i = 0; i < 4; i++) + { + result <<= 8; + + result += *next; + + if (order == MSBFirst) + { + next++; + } + else + { + next--; + } + } + + return result; +} + +void Put16(unsigned int value, char *buffer, int order) +{ + if (order == MSBFirst) + { + buffer[1] = (unsigned char) (value & 0xff); + + value >>= 8; + + *buffer = (unsigned char) value; + } + else + { + *buffer = (unsigned char) (value & 0xff); + + value >>= 8; + + buffer[1] = (unsigned char) value; + } +} + +void Put24(unsigned int value, char *buffer, int order) +{ + int i; + + if (order == MSBFirst) + { + buffer += 2; + + for (i = 3; i > 0; i--) + { + *buffer-- = (unsigned char) (value & 0xff); + + value >>= 8; + } + } + else + { + for (i = 3; i > 0; i--) + { + *buffer++ = (unsigned char) (value & 0xff); + + value >>= 8; + } + } +} + +void Put32(unsigned int value, char *buffer, int order) +{ + int i; + + if (order == MSBFirst) + { + buffer += 3; + + for (i = 4; i > 0; i--) + { + *buffer-- = (unsigned char) (value & 0xff); + + value >>= 8; + } + } + else + { + for (i = 4; i > 0; i--) + { + *buffer++ = (unsigned char) (value & 0xff); + + value >>= 8; + } + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixels.h b/nx-X11/programs/Xserver/hw/nxagent/Pixels.h new file mode 100644 index 000000000..f9f88233e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Pixels.h @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Pixels_H__ +#define __Pixels_H__ + +#include "Visual.h" +#include "Drawable.h" +#include "Composite.h" + +/* + * Count how many pixels are different + * in the image. + */ + +int nxagentUniquePixels(XImage *image); + +/* + * Convert a 32 bit pixel to 16 bit. + */ + +#define Color32to16(color) \ +do \ +{ \ + Visual *pVisual; \ +\ + pVisual = nxagentDefaultVisual(nxagentDefaultScreen); \ +\ + if (pVisual -> green_mask == 0x7e0) \ + { \ + /* \ + * bit mask 5-6-5 \ + */ \ +\ + color = (((color & (pVisual -> blue_mask << 3)) >> 3) | \ + ((color & (pVisual -> green_mask << 5)) >> 5) | \ + ((color & (pVisual -> red_mask << 8)) >> 8)); \ + } \ + else \ + { \ + /* \ + * bit mask 5-5-5 \ + */ \ +\ + color = (((color & (pVisual -> blue_mask << 3)) >> 3) | \ + ((color & (pVisual -> green_mask << 6)) >> 6) | \ + ((color & (pVisual -> red_mask << 9)) >> 9)); \ + } \ +} \ +while (0) + +/* + * Rules to break the synchronization loop. + */ + +#define breakOnBlocking(mask) \ + (((mask) != NEVER_BREAK) && ((mask) & BLOCKING_BREAK) && \ + nxagentBlocking == 1) + +#define breakOnCongestion(mask) \ + (((mask) != NEVER_BREAK) && ((mask) & CONGESTION_BREAK) && \ + nxagentCongestion > 4) + +#define breakOnBlockingOrCongestion(mask) \ + (breakOnBlocking(mask) != 0 || breakOnCongestion(mask) != 0) + +#define breakOnCongestionDrawable(mask, pDrawable) \ + (((mask) != NEVER_BREAK) && ((mask) & CONGESTION_BREAK) && \ + (nxagentCongestion > 4 || \ + ((pDrawable) -> type == DRAWABLE_PIXMAP && \ + nxagentCongestion > 1))) + +#define breakOnEvent(mask) \ + (((mask) != NEVER_BREAK) && ((mask) & EVENT_BREAK) && \ + nxagentUserInput(NULL) == 1) + +#define canBreakOnTimeout(mask) \ + (((mask) != NEVER_BREAK) && nxagentOption(Shadow) == 0) + +/* + * Macros defining the conditions to + * defer X requests. + */ + +#define NXAGENT_SHOULD_DEFER_TRAPEZOIDS(pDrawable) \ + (nxagentOption(DeferLevel) >= 2 && \ + nxagentDrawableContainGlyphs(pDrawable) == 0 && \ + nxagentOption(LinkType) < LINK_TYPE_ADSL && \ + nxagentCongestion > 4) + +/* +FIXME: The condition checking for the render + version is a workaround implemented to + avoid problems with the render composi- + te on XFree86 remote server. +*/ +#define NXAGENT_SHOULD_DEFER_COMPOSITE(pSrc, pMask, pDst) \ + ((nxagentRenderVersionMajor == 0 && \ + nxagentRenderVersionMinor == 8 && \ + (pDst) -> pDrawable -> type == DRAWABLE_PIXMAP) || \ + ((pDst) -> pDrawable -> type == DRAWABLE_PIXMAP && \ + (nxagentDrawableStatus((pSrc) -> pDrawable) == NotSynchronized || \ + ((pMask) && nxagentDrawableStatus((pMask) -> pDrawable) == NotSynchronized)) && \ + nxagentOption(DeferLevel) == 1) || \ + (nxagentOption(DeferLevel) >= 2 && \ + nxagentOption(LinkType) < LINK_TYPE_ADSL)) + +#define NXAGENT_SHOULD_DEFER_PUTIMAGE(pDrawable) \ + (nxagentSplitTrap == 0 && \ + nxagentOption(DeferLevel) > 0) + +/* + * Macros defining the conditions to + * start the synchronization loops of + * resources. + */ + +#define NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_WINDOWS(mask) \ + ((nxagentCorruptedWindows > 0 && breakOnBlockingOrCongestion(mask) == 0) || \ + mask == NEVER_BREAK) + +#define NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_BACKGROUNDS(mask) \ + ((nxagentCorruptedWindows == 0 && nxagentCorruptedBackgrounds > 0 && \ + breakOnBlockingOrCongestion(mask) == 0) || mask == NEVER_BREAK) + +#define NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_PIXMAPS(mask) \ + ((nxagentCorruptedWindows == 0 && nxagentCorruptedPixmaps > 0 && \ + nxagentCongestion == 0 && nxagentBlocking == 0) || \ + mask == NEVER_BREAK) + +/* + * Macros defining the conditions to + * synchronize a single resource. + */ + +#define NXAGENT_SHOULD_SYNCHRONIZE_WINDOW(pDrawable) \ + (nxagentWindowIsVisible((WindowPtr) pDrawable) == 1 && \ + (nxagentDefaultWindowIsVisible() == 1 || nxagentCompositeEnable == 1)) + +#define MINIMUM_PIXMAP_USAGE_COUNTER 2 + +#define NXAGENT_SHOULD_SYNCHRONIZE_PIXMAP(pDrawable) \ + (nxagentPixmapUsageCounter((PixmapPtr) pDrawable) >= \ + MINIMUM_PIXMAP_USAGE_COUNTER || \ + nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1) + +#endif /* __Pixels_H__ */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixmap.c b/nx-X11/programs/Xserver/hw/nxagent/Pixmap.c new file mode 100644 index 000000000..4aea92e2d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Pixmap.c @@ -0,0 +1,1646 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "scrnintstr.h" +#include "miscstruct.h" +#include "pixmapstr.h" +#include "dixstruct.h" +#include "regionstr.h" +#include "../../include/gc.h" +#include "servermd.h" +#include "mi.h" + +#include "../../fb/fb.h" + +#include "Agent.h" +#include "Display.h" +#include "Screen.h" +#include "Pixmaps.h" +#include "Trap.h" +#include "GCs.h" +#include "GCOps.h" +#include "Image.h" +#include "Split.h" +#include "Drawable.h" +#include "Visual.h" +#include "Client.h" +#include "Events.h" +#include "Holder.h" +#include "Args.h" + +#include "NXlib.h" +#include "NXpack.h" + +RESTYPE RT_NX_PIXMAP; + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +#ifdef TEST +#include "Font.h" +#endif + +int nxagentPixmapPrivateIndex; + +int nxagentCorruptedPixmaps; +int nxagentCorruptedBackgrounds; + +/* + * Force deallocation of the virtual pixmap. + */ + +static Bool nxagentDestroyVirtualPixmap(PixmapPtr pPixmap); + +/* + * This serves as a tool to check the synchronization + * between pixmaps in framebuffer and the correspondent + * pixmaps in the real X server. + */ + +#ifdef TEST +Bool nxagentCheckPixmapIntegrity(PixmapPtr pPixmap); +#endif + +struct nxagentPixmapPair +{ + Pixmap pixmap; + PixmapPtr pMap; +}; + +PixmapPtr nxagentCreatePixmap(ScreenPtr pScreen, int width, + int height, int depth) +{ + nxagentPrivPixmapPtr pPixmapPriv, pVirtualPriv; + + PixmapPtr pPixmap; + PixmapPtr pVirtual; + + #ifdef DEBUG + fprintf(stderr, "nxagentCreatePixmap: Creating pixmap with width [%d] " + "height [%d] depth [%d].\n", width, height, depth); + #endif + + /* + * Create the pixmap structure but do + * not allocate memory for the data. + */ + + pPixmap = AllocatePixmap(pScreen, 0); + + if (!pPixmap) + { + #ifdef WARNING + fprintf(stderr, "nxagentCreatePixmap: WARNING! Failed to create pixmap with " + "width [%d] height [%d] depth [%d].\n", width, height, depth); + #endif + + return NullPixmap; + } + + /* + * Initialize the core members. + */ + + pPixmap -> drawable.type = DRAWABLE_PIXMAP; + pPixmap -> drawable.class = 0; + pPixmap -> drawable.pScreen = pScreen; + pPixmap -> drawable.depth = depth; + pPixmap -> drawable.bitsPerPixel = BitsPerPixel(depth); + pPixmap -> drawable.id = 0; + pPixmap -> drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap -> drawable.x = 0; + pPixmap -> drawable.y = 0; + pPixmap -> drawable.width = width; + pPixmap -> drawable.height = height; + pPixmap -> devKind = 0; + pPixmap -> refcnt = 1; + pPixmap -> devPrivate.ptr = NULL; + + /* + * Initialize the privates of the real picture. + */ + + pPixmapPriv = nxagentPixmapPriv(pPixmap); + + pPixmapPriv -> isVirtual = False; + pPixmapPriv -> isShared = nxagentShmPixmapTrap; + + /* + * The shared memory pixmaps are never + * synchronized with the remote X Server. + */ + + if (pPixmapPriv -> isShared == 1) + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = width; + box.y2 = height; + + pPixmapPriv -> corruptedRegion = REGION_CREATE(pPixmap -> drawable.pScreen, &box, 1); + } + else + { + pPixmapPriv -> corruptedRegion = REGION_CREATE(pPixmap -> drawable.pScreen, (BoxRec *) NULL, 1); + } + + pPixmapPriv -> corruptedBackground = 0; + + pPixmapPriv -> containGlyphs = 0; + pPixmapPriv -> containTrapezoids = 0; + + /* + * The lazy encoding policy generally does + * not send on remote X server the off-screen + * images, by preferring to synchronize the + * windows content. Anyway this behaviour may + * be inadvisable if a pixmap is used, for + * example, for multiple copy areas on screen. + * This counter serves the purpose, taking in- + * to account the number of times the pixmap + * has been used as source for a deferred + * operation. + */ + + pPixmapPriv -> usageCounter = 0; + + pPixmapPriv -> corruptedBackgroundId = 0; + pPixmapPriv -> corruptedId = 0; + + pPixmapPriv -> synchronizationBitmap = NullPixmap; + + pPixmapPriv -> corruptedTimestamp = 0; + + pPixmapPriv -> splitResource = NULL; + + pPixmapPriv -> isBackingPixmap = 0; + + /* + * Create the pixmap based on the default + * windows. The proxy knows this and uses + * this information to optimize encode the + * create pixmap message by including the + * id of the drawable in the checksum. + */ + + if (width != 0 && height != 0 && nxagentGCTrap == 0) + { + pPixmapPriv -> id = XCreatePixmap(nxagentDisplay, + nxagentDefaultWindows[pScreen -> myNum], + width, height, depth); + } + else + { + pPixmapPriv -> id = 0; + + #ifdef TEST + fprintf(stderr, "nxagentCreatePixmap: Skipping the creation of pixmap at [%p] on real " + "X server with nxagentGCTrap [%d].\n", (void *) pPixmap, nxagentGCTrap); + #endif + } + + pPixmapPriv -> mid = FakeClientID(serverClient -> index); + + AddResource(pPixmapPriv -> mid, RT_NX_PIXMAP, pPixmap); + + pPixmapPriv -> pRealPixmap = pPixmap; + pPixmapPriv -> pVirtualPixmap = NULL; + pPixmapPriv -> pPicture = NULL; + + /* + * Create the pixmap in the virtual framebuffer. + */ + + pVirtual = fbCreatePixmap(pScreen, width, height, depth); + + if (pVirtual == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentCreatePixmap: PANIC! Failed to create virtual pixmap with " + "width [%d] height [%d] depth [%d].\n", width, height, depth); + #endif + + nxagentDestroyPixmap(pPixmap); + + return NullPixmap; + } + + #ifdef TEST + fprintf(stderr,"nxagentCreatePixmap: Allocated memory for the Virtual %sPixmap %p of real Pixmap %p (%dx%d)\n", + nxagentShmPixmapTrap ? "Shm " : "", (void *) pVirtual, (void *) pPixmap, width, height); + #endif + + pPixmapPriv -> pVirtualPixmap = pVirtual; + + /* + * Initialize the privates of the virtual picture. We + * could avoid to use a flag and just check the pointer + * to the virtual pixmap that, if the pixmap is actually + * virtual, will be NULL. Unfortunately the flag can be + * changed in nxagentValidateGC(). That code should be + * removed in future. + */ + + pVirtualPriv = nxagentPixmapPriv(pVirtual); + + pVirtualPriv -> isVirtual = True; + pVirtualPriv -> isShared = nxagentShmPixmapTrap; + + pVirtualPriv -> corruptedRegion = REGION_CREATE(pVirtual -> drawable.pScreen, (BoxRec *) NULL, 1); + + pVirtualPriv -> corruptedBackground = 0; + + pVirtualPriv -> containGlyphs = 0; + pVirtualPriv -> containTrapezoids = 0; + + pVirtualPriv -> usageCounter = 0; + + pVirtualPriv -> corruptedBackgroundId = 0; + pVirtualPriv -> corruptedId = 0; + + pVirtualPriv -> synchronizationBitmap = NullPixmap; + + pVirtualPriv -> corruptedTimestamp = 0; + + pVirtualPriv -> splitResource = NULL; + + /* + * We might distinguish real and virtual pixmaps by + * checking the pointers to pVirtualPixmap. We should + * also remove the copy of id and use the one of the + * real pixmap. + */ + + pVirtualPriv -> id = pPixmapPriv -> id; + pVirtualPriv -> mid = 0; + + /* + * Storing a pointer back to the real pixmap is + * silly. Unfortunately this is the way it has + * been originally implemented. See also the + * comment in destroy of the pixmap. + */ + + pVirtualPriv -> pRealPixmap = pPixmap; + pVirtualPriv -> pVirtualPixmap = NULL; + pVirtualPriv -> pPicture = NULL; + + /* + * Check that the virtual pixmap is created with + * the appropriate bits-per-plane, otherwise free + * everything and return. + */ + + if (pVirtual -> drawable.bitsPerPixel == 0) + { + #ifdef WARNING + + fprintf(stderr, "nxagentCreatePixmap: WARNING! Virtual pixmap at [%p] has invalid " + "bits per pixel.\n", (void *) pVirtual); + + fprintf(stderr, "nxagentCreatePixmap: WARNING! Real pixmap created with width [%d] " + "height [%d] depth [%d] bits per pixel [%d].\n", pPixmap -> drawable.width, + pPixmap -> drawable.height = height, pPixmap -> drawable.depth, + pPixmap -> drawable.bitsPerPixel); + + #endif + + if (!nxagentRenderTrap) + { + #ifdef WARNING + fprintf(stderr, "Warning: Disabling render extension due to missing pixmap format.\n"); + #endif + + nxagentRenderTrap = 1; + } + + nxagentDestroyPixmap(pPixmap); + + return NullPixmap; + } + + #ifdef TEST + fprintf(stderr, "nxagentCreatePixmap: Created pixmap at [%p] virtual at [%p] with width [%d] " + "height [%d] depth [%d].\n", (void *) pPixmap, (void *) pVirtual, + width, height, depth); + #endif + + return pPixmap; +} + +Bool nxagentDestroyPixmap(PixmapPtr pPixmap) +{ + PixmapPtr pVirtual; + + nxagentPrivPixmapPtr pPixmapPriv; + + if (!pPixmap) + { + #ifdef PANIC + fprintf(stderr, "nxagentDestroyPixmap: PANIC! Invalid attempt to destroy " + "a null pixmap pointer.\n"); + #endif + + return False; + } + + pPixmapPriv = nxagentPixmapPriv(pPixmap); + + pVirtual = pPixmapPriv -> pVirtualPixmap; + + #ifdef TEST + fprintf(stderr, "nxagentDestroyPixmap: Destroying pixmap at [%p] with virtual at [%p].\n", + (void *) pPixmap, (void *) pVirtual); + #endif + + if (pPixmapPriv -> isVirtual) + { + int refcnt; + + /* + * For some pixmaps we receive the destroy only for the + * virtual. Infact to draw in the framebuffer we can use + * the virtual pixmap instead of the pointer to the real + * one. As the virtual pixmap can collect references, we + * must transfer those references to the real pixmap so + * we can continue as the destroy had been requested for + * it. + */ + + pVirtual = pPixmap; + pPixmap = pPixmapPriv -> pRealPixmap; + + pPixmapPriv = nxagentPixmapPriv(pPixmap); + + /* + * Move the references accumulated by the virtual + * pixmap into the references of the real one. + */ + + refcnt = pVirtual -> refcnt - 1; + + #ifdef TEST + fprintf(stderr, "nxagentDestroyPixmap: Adding [%d] references to pixmap at [%p].\n", + refcnt, (void *) pPixmap); + #endif + + pPixmap -> refcnt += refcnt; + + pVirtual -> refcnt -= refcnt; + } + + --pPixmap -> refcnt; + + #ifdef TEST + + fprintf(stderr, "nxagentDestroyPixmap: Pixmap has now [%d] references with virtual pixmap [%d].\n", + pPixmap -> refcnt, pVirtual -> refcnt); + + if (pVirtual != NULL && pVirtual -> refcnt != 1) + { + fprintf(stderr, "nxagentDestroyPixmap: PANIC! Virtual pixmap has [%d] references.\n", + pVirtual -> refcnt); + } + + #endif + + if (pPixmap -> refcnt > 0) + { + return True; + } + + #ifdef TEST + + fprintf(stderr, "nxagentDestroyPixmap: Managing to destroy the pixmap at [%p]\n", + (void *) pPixmap); + #endif + + nxagentRemoveItemBSPixmapList(nxagentPixmap(pPixmap)); + + nxagentDestroyVirtualPixmap(pPixmap); + + if (pPixmapPriv -> corruptedRegion != NullRegion) + { + REGION_DESTROY(pPixmap -> drawable.pScreen, pPixmapPriv -> corruptedRegion); + + pPixmapPriv -> corruptedRegion = NullRegion; + } + + if (nxagentSynchronization.pDrawable == (DrawablePtr) pPixmap) + { + nxagentSynchronization.pDrawable = NULL; + + #ifdef TEST + fprintf(stderr, "nxagentDestroyPixmap: Synchronization drawable [%p] removed from resources.\n", + (void *) pPixmap); + #endif + } + + nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_BACKGROUND); + + nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP); + + nxagentDestroyDrawableBitmap((DrawablePtr) pPixmap); + + if (pPixmapPriv -> splitResource != NULL) + { + nxagentReleaseSplit((DrawablePtr) pPixmap); + } + + /* + * A pixmap with width and height set to 0 is + * created at the beginning. To this pixmap is + * not assigned an id. This is likely a scratch + * pixmap used by the X server. + */ + + if (pPixmapPriv -> id) + { + XFreePixmap(nxagentDisplay, pPixmapPriv -> id); + } + + if (pPixmapPriv -> mid) + { + FreeResource(pPixmapPriv -> mid, RT_NONE); + } + + xfree(pPixmap); + + return True; +} + +Bool nxagentDestroyVirtualPixmap(PixmapPtr pPixmap) +{ + PixmapPtr pVirtual; + nxagentPrivPixmapPtr pVirtualPriv; + + pVirtual = nxagentPixmapPriv(pPixmap) -> pVirtualPixmap; + + /* + * Force the routine to get rid of the virtual + * pixmap. + */ + + if (pVirtual != NULL) + { + pVirtual -> refcnt = 1; + + pVirtualPriv = nxagentPixmapPriv(pVirtual); + + if (pVirtualPriv -> corruptedRegion != NullRegion) + { + REGION_DESTROY(pVirtual -> drawable.pScreen, pVirtualPriv -> corruptedRegion); + + pVirtualPriv -> corruptedRegion = NullRegion; + } + + fbDestroyPixmap(pVirtual); + } + + return True; +} + +RegionPtr nxagentPixmapToRegion(PixmapPtr pPixmap) +{ + #ifdef TEST + fprintf(stderr, "PixmapToRegion: Pixmap = [%p] nxagentVirtualPixmap = [%p]\n", + (void *) pPixmap, (void *) nxagentVirtualPixmap(pPixmap)); + #endif + + return fbPixmapToRegion(nxagentVirtualPixmap(pPixmap)); +} + +Bool nxagentModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, + int bitsPerPixel, int devKind, pointer pPixData) +{ + PixmapPtr pVirtualPixmap; + + /* + * See miModifyPixmapHeader() in miscrinit.c. This + * function is used to recycle the scratch pixmap + * for this screen. We let it refer to the virtual + * pixmap. + */ + + if (!pPixmap) + { + return False; + } + + if (nxagentPixmapIsVirtual(pPixmap)) + { + #ifdef PANIC + fprintf(stderr, "nxagentModifyPixmapHeader: PANIC! Pixmap at [%p] is virtual.\n", + (void *) pPixmap); + #endif + + FatalError("nxagentModifyPixmapHeader: PANIC! Pixmap is virtual."); + } + + pVirtualPixmap = nxagentVirtualPixmap(pPixmap); + + #ifdef TEST + fprintf(stderr, "nxagentModifyPixmapHeader: Pixmap at [%p] Virtual at [%p].\n", + (void *) pPixmap, (void *) pVirtualPixmap); + + fprintf(stderr, "nxagentModifyPixmapHeader: Pixmap has width [%d] height [%d] depth [%d] " + "bits-per-pixel [%d] devKind [%d] pPixData [%p].\n", pPixmap->drawable.width, + pPixmap->drawable.height, pPixmap->drawable.depth, pPixmap->drawable.bitsPerPixel, + pPixmap->devKind, (void *) pPixmap->devPrivate.ptr); + + fprintf(stderr, "nxagentModifyPixmapHeader: New parameters are width [%d] height [%d] depth [%d] " + "bits-per-pixel [%d] devKind [%d] pPixData [%p].\n", width, height, depth, + bitsPerPixel, devKind, (void *) pPixData); + #endif + + if ((width > 0) && (height > 0) && (depth > 0) && + (bitsPerPixel > 0) && (devKind > 0) && pPixData) + { + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bitsPerPixel; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = devKind; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = pPixData; + + pVirtualPixmap->drawable.depth = depth; + pVirtualPixmap->drawable.bitsPerPixel = bitsPerPixel; + pVirtualPixmap->drawable.id = 0; + pVirtualPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pVirtualPixmap->drawable.x = 0; + pVirtualPixmap->drawable.y = 0; + pVirtualPixmap->drawable.width = width; + pVirtualPixmap->drawable.height = height; + pVirtualPixmap->devKind = devKind; + pVirtualPixmap->refcnt = 1; + pVirtualPixmap->devPrivate.ptr = pPixData; + } + else + { + if (width > 0) + pPixmap->drawable.width = width; + + if (height > 0) + pPixmap->drawable.height = height; + + if (depth > 0) + pPixmap->drawable.depth = depth; + + if (bitsPerPixel > 0) + pPixmap->drawable.bitsPerPixel = bitsPerPixel; + else if ((bitsPerPixel < 0) && (depth > 0)) + pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth); + + if (devKind > 0) + pPixmap->devKind = devKind; + else if ((devKind < 0) && ((width > 0) || (depth > 0))) + pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width, + pPixmap->drawable.depth); + + if (pPixData) + pPixmap->devPrivate.ptr = pPixData; + + /* + * XXX This was the previous assignment: + * + * pVirtualPixmap->devPrivate.ptr = pPixData; + */ + + if (width > 0) + pVirtualPixmap->drawable.width = width; + + if (height > 0) + pVirtualPixmap->drawable.height = height; + + if (depth > 0) + pVirtualPixmap->drawable.depth = depth; + + if (bitsPerPixel > 0) + pVirtualPixmap->drawable.bitsPerPixel = bitsPerPixel; + else if ((bitsPerPixel < 0) && (depth > 0)) + pVirtualPixmap->drawable.bitsPerPixel = BitsPerPixel(depth); + + if (devKind > 0) + pVirtualPixmap->devKind = devKind; + else if ((devKind < 0) && ((width > 0) || (depth > 0))) + pVirtualPixmap->devKind = PixmapBytePad(pVirtualPixmap->drawable.width, + pVirtualPixmap->drawable.depth); + + if (pPixData) + pVirtualPixmap->devPrivate.ptr = pPixData; + + #ifdef PANIC + + if (pPixmap->drawable.x != 0 || pPixmap->drawable.y != 0) + { + fprintf(stderr, "nxagentModifyPixmapHeader: PANIC! Pixmap at [%p] has x [%d] and y [%d].\n", + (void *) pPixmap, pPixmap->drawable.x, pPixmap->drawable.y); + + FatalError("nxagentModifyPixmapHeader: PANIC! Pixmap has x or y greater than zero."); + } + + #endif + } + + return True; +} + +static void nxagentPixmapMatchID(void *p0, XID x1, void *p2) +{ + PixmapPtr pPixmap = (PixmapPtr)p0; + struct nxagentPixmapPair *pPair = p2; + + if ((pPair -> pMap == NULL) && (nxagentPixmap(pPixmap) == pPair -> pixmap)) + { + pPair -> pMap = pPixmap; + } +} + +PixmapPtr nxagentPixmapPtr(Pixmap pixmap) +{ + int i; + struct nxagentPixmapPair pair; + + if (pixmap == None) + { + return NULL; + } + + pair.pixmap = pixmap; + pair.pMap = NULL; + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP, + nxagentPixmapMatchID, &pair); + + for (i = 0; (pair.pMap == NULL) && (i < MAXCLIENTS); i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], RT_PIXMAP, + nxagentPixmapMatchID, &pair); + } + } + + #ifdef WARNING + + if (pair.pMap == NULL) + { + fprintf(stderr, "nxagentFindPixmap: WARNING! Failed to find " + "remote pixmap [%ld].\n", (long int) pair.pixmap); + } + else if (nxagentDrawableStatus((DrawablePtr) pair.pMap) == NotSynchronized) + { + fprintf(stderr, "WARNING! Rootless icon at [%p] [%d,%d] is not synchronized.\n", + (void *) pair.pMap, pair.pMap -> drawable.width, + pair.pMap -> drawable.height); + } + + #endif + + return pair.pMap; +} + +/* + * Reconnection stuff. + */ + +int nxagentDestroyNewPixmapResourceType(pointer p, XID id) +{ + /* + * Address of the destructor is set in Init.c. + */ + + #ifdef TEST + fprintf(stderr, "nxagentDestroyNewPixmapResourceType: Destroying mirror id [%ld] for pixmap at [%p].\n", + nxagentPixmapPriv((PixmapPtr) p) -> mid, (void *) p); + #endif + + nxagentPixmapPriv((PixmapPtr) p) -> mid = None; + + return True; +} + +void nxagentDisconnectPixmap(void *p0, XID x1, void *p2) +{ + PixmapPtr pPixmap = (PixmapPtr) p0; + + Bool *pBool; + + pBool = (Bool*) p2; + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectPixmap: Called with bool [%d] and pixmap at [%p].\n", + *pBool, (void *) pPixmap); + + fprintf(stderr, "nxagentDisconnectPixmap: Virtual pixmap is [%ld].\n", + nxagentPixmap(pPixmap)); + #endif + + nxagentPixmap(pPixmap) = None; + + if (nxagentDrawableStatus((DrawablePtr) pPixmap) == NotSynchronized) + { + nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_BACKGROUND); + + nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP); + } +} + +Bool nxagentDisconnectAllPixmaps() +{ + int r = 1; + int i; + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectAllPixmaps: Going to iterate through pixmap resources.\n"); + #endif + + /* + * The RT_NX_PIXMAP resource type is allocated + * only on the server client, so we don't need + * to find it through the other clients too. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP, nxagentDisconnectPixmap, &r); + + #ifdef WARNING + + if (r == 0) + { + fprintf(stderr, "nxagentDisconnectAllPixmaps: WARNING! Failed to disconnect " + "pixmap for client [%d].\n", serverClient -> index); + } + + #endif + + for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++) + { + if (clients[i]) + { + #ifdef TEST + fprintf(stderr, "nxagentDisconnectAllPixmaps: Going to disconnect pixmaps of client [%d].\n", i); + #endif + + FindClientResourcesByType(clients[i], RT_PIXMAP, nxagentDisconnectPixmap, &r); + + #ifdef WARNING + + if (r == 0) + { + fprintf(stderr, "nxagentDisconnectAllPixmaps: WARNING! Failed to disconnect " + "pixmap for client [%d].\n", i); + } + + #endif + } + } + + #ifdef WARNING + + if (r == 0) + { + fprintf(stderr, "nxagentDisconnectAllPixmaps: WARNING! Failed to disconnect " + "pixmap for client [%d].\n", i); + } + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectAllPixmaps: Pixmaps disconnection completed.\n"); + #endif + + return r; +} + +void nxagentReconnectPixmap(void *p0, XID x1, void *p2) +{ + PixmapPtr pPixmap = (PixmapPtr) p0; + Bool *pBool = (Bool*) p2; + nxagentPrivPixmapPtr pPixmapPriv; + + if (*pBool == 0 || pPixmap == NULL || + NXDisplayError(nxagentDisplay) == 1) + { + *pBool = 0; + + #ifdef TEST + fprintf(stderr, "nxagentReconnectPixmap: Ignoring pixmap at [%p] while " + "recovering from the error.\n", (void *) pPixmap); + #endif + + return; + } + else if (pPixmap == nxagentDefaultScreen -> pScratchPixmap) + { + /* + * Every time the scratch pixmap is used its + * data is changed, so we don't need to recon- + * nect it. + */ + + #ifdef TEST + fprintf(stderr, "nxagentReconnectPixmap: Ignoring scratch pixmap at [%p].\n", + (void *) pPixmap); + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentReconnectPixmap: Called with result [%d] and pixmap at [%p].\n", + *pBool, (void *) pPixmap); + + fprintf(stderr, "nxagentReconnectPixmap: Virtual pixmap is at [%p] picture is at [%p].\n", + (void *) nxagentPixmapPriv(pPixmap) -> pVirtualPixmap, + (void *) nxagentPixmapPriv(pPixmap) -> pPicture); + #endif + + pPixmapPriv = nxagentPixmapPriv(pPixmap); + + if (pPixmap -> drawable.width && pPixmap -> drawable.height) + { + pPixmapPriv -> id = XCreatePixmap(nxagentDisplay, + nxagentDefaultWindows[pPixmap -> drawable.pScreen -> myNum], + pPixmap -> drawable.width, + pPixmap -> drawable.height, + pPixmap -> drawable.depth); + + nxagentPixmap(pPixmapPriv -> pVirtualPixmap) = pPixmapPriv -> id; + + #ifdef TEST + fprintf(stderr, "nxagentReconnectPixmap: Created virtual pixmap with id [%ld] for pixmap at [%p].\n", + nxagentPixmap(pPixmap), (void *) pPixmap); + #endif + + if (pPixmap == (PixmapPtr) nxagentDefaultScreen -> devPrivate) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectPixmap: WARNING! Pixmap is root screen. Returning.\n"); + #endif + + return; + } + + nxagentSplitTrap = 1; + + *pBool = nxagentSynchronizeDrawableData((DrawablePtr) pPixmap, NEVER_BREAK, NULL); + + nxagentSplitTrap = 0; + + if (*pBool == 0) + { + #ifdef PANIC + fprintf(stderr, "nxagentReconnectPixmap: PANIC! Failed to synchronize the pixmap.\n"); + #endif + } + + + if (nxagentDrawableStatus((DrawablePtr) pPixmap) == NotSynchronized) + { + if (nxagentIsCorruptedBackground(pPixmap) == 1) + { + nxagentAllocateCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_BACKGROUND); + + nxagentFillRemoteRegion((DrawablePtr) pPixmap, + nxagentCorruptedRegion((DrawablePtr) pPixmap)); + } + else + { + nxagentAllocateCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP); + } + } + } +} + +Bool nxagentReconnectAllPixmaps(void *p0) +{ + Bool result = 1; + + int i; + + #ifdef TEST + fprintf(stderr, "nxagentReconnectAllPixmaps: Going to recreate all pixmaps.\n"); + #endif + + /* + * Reset the geometry and alpha information + * used by proxy to unpack the packed images. + */ + + nxagentResetVisualCache(); + + nxagentResetAlphaCache(); + + /* + * The RT_NX_PIXMAP resource type is allocated + * only on the server client, so we don't need + * to find it through the other clients too. + */ + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP, nxagentReconnectPixmap, &result); + + #ifdef WARNING + + if (result == 0) + { + fprintf(stderr, "nxagentReconnectAllPixmaps: WARNING! Failed to reconnect " + "pixmap for client [%d].\n", serverClient -> index); + } + + #endif + + for (i = 0, result = 1; i < MAXCLIENTS; result = 1, i++) + { + if (clients[i] != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentReconnectAllPixmaps: Going to reconnect pixmaps of client [%d].\n", i); + #endif + + /* + * Let the pixmap be reconnected as it was an + * image request issued by the client owning + * the resource. The client index is used as + * a subscript by the image routines to cache + * the data per-client. + */ + + FindClientResourcesByType(clients[i], RT_PIXMAP, nxagentReconnectPixmap, &result); + + #ifdef WARNING + + if (result == 0) + { + fprintf(stderr, "nxagentReconnectAllPixmaps: WARNING! Failed to reconnect " + "pixmap for client [%d].\n", serverClient -> index); + } + + #endif + } + } + + #ifdef TEST + fprintf(stderr, "nxagentReconnectAllPixmaps: Pixmaps reconnection completed.\n"); + #endif + + return result; +} + +#ifdef TEST + +static void nxagentCheckOnePixmapIntegrity(void *p0, XID x1, void *p2) +{ + PixmapPtr pPixmap = (PixmapPtr) p0; + Bool *pBool = (Bool*) p2; + + if (*pBool == False) + { + return; + } + + if (pPixmap == nxagentDefaultScreen -> devPrivate) + { + #ifdef TEST + fprintf(stderr, "nxagentCheckOnePixmapIntegrity: pixmap %p is screen.\n", + (void *) pPixmap); + #endif + + return; + } + + if (pPixmap == nxagentDefaultScreen -> PixmapPerDepth[0]) + { + #ifdef TEST + fprintf(stderr, "nxagentCheckOnePixmapIntegrity: pixmap %p is default stipple of screen.\n", + (void *) pPixmap); + #endif + + return; + } + + *pBool = nxagentCheckPixmapIntegrity(pPixmap); +} + +Bool nxagentCheckPixmapIntegrity(PixmapPtr pPixmap) +{ + Bool integrity = 1; + XImage *image; + char *data; + int format; + unsigned long plane_mask = AllPlanes; + unsigned int width, height, length, depth; + PixmapPtr pVirtual = nxagentVirtualPixmap(pPixmap); + + width = pPixmap -> drawable.width; + height = pPixmap -> drawable.height; + depth = pPixmap -> drawable.depth; + format = (depth == 1) ? XYPixmap : ZPixmap; + + if (width && height) + { + length = nxagentImageLength(width, height, format, 0, depth); + + data = malloc(length); + + if (data == NULL) + { + FatalError("nxagentCheckPixmapIntegrity: Failed to allocate a buffer of size %d.\n", length); + } + + image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), 0, 0, + width, height, plane_mask, format); + if (image == NULL) + { + FatalError("XGetImage: Failed.\n"); + + free(data); + + return False; + } + + #ifdef WARNING + fprintf(stderr, "nxagentCheckPixmapIntegrity: Image from X has length [%d] and checksum [0x%s].\n", + length, nxagentChecksum(image->data, length)); + #endif + + NXCleanImage(image); + + #ifdef WARNING + fprintf(stderr, "nxagentCheckPixmapIntegrity: Image after clean has checksum [0x%s].\n", + nxagentChecksum(image->data, length)); + #endif + + fbGetImage((DrawablePtr) pVirtual, 0, 0, width, height, format, plane_mask, data); + + #ifdef WARNING + fprintf(stderr, "nxagentCheckPixmapIntegrity: Image from FB has length [%d] and checksum [0x%s].\n", + length, nxagentChecksum(data, length)); + #endif + + if (image != NULL && memcmp(image -> data, data, length) != 0) + { + integrity = 0; + } + else + { + integrity = 1; + + #ifdef TEST + fprintf(stderr, "nxagentCheckPixmapIntegrity: Pixmap at [%p] has been realized. " + "Now remote and frambuffer data are synchronized.\n", (void *) pPixmap); + #endif + } + + #ifdef WARNING + + if (integrity == 0) + { + + int i; + char *p, *q; + + for (i = 0, p = image -> data, q = data; i < length; i++) + { + if (p[i] != q[i]) + { + fprintf(stderr, "nxagentCheckPixmapIntegrity: Byte [%d] image -> data [%d] data [%d]. " + "Buffers differ!\n", i, p[i], q[i]); + } + else + { + fprintf(stderr, "nxagentCheckPixmapIntegrity: Byte [%d] image -> data [%d] data [%d].\n", + i, p[i], q[i]); + } + } + + fprintf(stderr, "nxagentCheckPixmapIntegrity: Pixmap at [%p] width [%d], height [%d], has been realized " + "but the data buffer still differs.\n", (void *) pPixmap, width, height); + + fprintf(stderr, "nxagentCheckPixmapIntegrity: bytes_per_line [%d] byte pad [%d] format [%d].\n", + image -> bytes_per_line, nxagentImagePad(width, height, 0, depth), image -> format); + + FatalError("nxagentCheckPixmapIntegrity: Image is corrupted!!\n"); + + } + + #endif + + if (image != NULL) + { + XDestroyImage(image); + } + + if (data != NULL) + { + free(data); + } + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckPixmapIntegrity: Ignored pixmap at [%p] with geometry [%d] [%d].\n", + (void *) pPixmap, width, height); + #endif + } + + return integrity; +} + +Bool nxagentCheckAllPixmapIntegrity() +{ + int i; + Bool imageIsGood = True; + + #ifdef TEST + fprintf(stderr, "nxagentCheckAllPixmapIntegrity\n"); + #endif + + FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP, + nxagentCheckOnePixmapIntegrity, &imageIsGood); + + for (i = 0; (i < MAXCLIENTS) && (imageIsGood); i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], RT_PIXMAP, + nxagentCheckOnePixmapIntegrity, &imageIsGood); + + } + } + + #ifdef TEST + fprintf(stderr, "nxagentCheckAllPixmapIntegrity: pixmaps integrity = %d.\n", imageIsGood); + #endif + + return imageIsGood; +} + +#endif + +void nxagentSynchronizeShmPixmap(DrawablePtr pDrawable, int xPict, int yPict, + int wPict, int hPict) +{ + GCPtr pGC; + char *data; + int width, height; + int depth, length, format; + CARD32 attributes[3]; + + int saveTrap; + + if (pDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pDrawable) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentSynchronizeShmPixmap: WARNING! Synchronizing shared pixmap at [%p].\n", + (void *) pDrawable); + #endif + + pGC = nxagentGetScratchGC(pDrawable -> depth, pDrawable -> pScreen); + + attributes[0] = 0x228b22; + attributes[1] = 0xffffff; + attributes[2] = FillSolid; + + ChangeGC(pGC, GCForeground | GCBackground | GCFillStyle, attributes); + + ValidateGC(pDrawable, pGC); + + width = (wPict != 0 && wPict <= pDrawable -> width) ? wPict : pDrawable -> width; + height = (hPict != 0 && hPict <= pDrawable -> height) ? hPict : pDrawable -> height; + + depth = pDrawable -> depth; + + format = (depth == 1) ? XYPixmap : ZPixmap; + + length = nxagentImageLength(width, height, format, 0, depth); + + saveTrap = nxagentGCTrap; + + nxagentGCTrap = 0; + + nxagentSplitTrap = 1; + + nxagentFBTrap = 1; + + if ((data = xalloc(length)) != NULL) + { + fbGetImage(nxagentVirtualDrawable(pDrawable), xPict, yPict, + width, height, format, 0xffffffff, data); + + nxagentPutImage(pDrawable, pGC, depth, xPict, yPict, + width, height, 0, format, data); + + xfree(data); + } + #ifdef WARNING + else + { + fprintf(stderr, "nxagentSynchronizeShmPixmap: WARNING! Failed to allocate memory for the operation.\n"); + } + #endif + + nxagentGCTrap = saveTrap; + + nxagentSplitTrap = 0; + + nxagentFBTrap = 0; + + nxagentFreeScratchGC(pGC); + } +} + +#ifdef DUMP + +/* + * This function is useful to visualize a pixmap and check + * its data consistency. To avoid the creation of many + * windows, one pixmap only can be monitored at a time. + */ + +Bool nxagentPixmapOnShadowDisplay(PixmapPtr pMap) +{ + static Display *shadow; + static Window win; + static int init = True; + static int showTime; + static PixmapPtr pPixmap; + static int depth; + static int width; + static int height; + static int length; + static unsigned int format; + + XlibGC gc; + XGCValues value; + XImage *image; + Visual *pVisual; + char *data = NULL; + + + if (init) + { + if (pMap == NULL) + { + return False; + } + else + { + pPixmap = pMap; + } + + depth = pPixmap -> drawable.depth; + width = pPixmap -> drawable.width; + height = pPixmap -> drawable.height; + format = (depth == 1) ? XYPixmap : ZPixmap; + + shadow = XOpenDisplay("localhost:0"); + + if (shadow == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentPixmapOnShadowDisplay: WARNING! Shadow display not opened.\n"); + #endif + + return False; + } + + init = False; + + win = XCreateSimpleWindow(shadow, DefaultRootWindow(shadow), 0, 0, + width, height, 0, 0xFFCC33, 0xFF); + + XMapWindow(shadow, win); + XClearWindow(shadow, win); + } + +/* +FIXME: If the pixmap has a different depth from the window, the + XPutImage returns a BadMatch. For example this may happens if + the Render extension is enabled. + Can we fix this creating a new pixmap? +*/ + + if (DisplayPlanes(shadow, DefaultScreen(shadow)) != depth) + { + #ifdef WARNING + fprintf(stderr, "nxagentPixmapOnShadowDisplay: Pixmap and Window depths [%d - %d] are not equals!\n", + depth, DisplayPlanes(shadow, DefaultScreen(shadow))); + #endif + + return False; + } + + /* + * If the framebuffer is updated continuously, the nxagent + * visualization become too much slow. + */ + + if ((GetTimeInMillis() - showTime) < 500) + { + return False; + } + + showTime = GetTimeInMillis(); + + length = nxagentImageLength(width, height, format, 0, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentPixmapOnShadowDisplay: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + return False; + } + + fbGetImage((DrawablePtr) nxagentVirtualPixmap(pPixmap), 0, 0, + width, height, format, AllPlanes, data); + + pVisual = nxagentImageVisual((DrawablePtr) pPixmap, depth); + + if (pVisual == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentPixmapOnShadowDisplay: WARNING! Visual not found. Using default visual.\n"); + #endif + + pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual; + } + + image = XCreateImage(nxagentDisplay, pVisual, + depth, format, 0, (char *) data, + width, height, BitmapPad(nxagentDisplay), + nxagentImagePad(width, format, 0, depth)); + + if (image == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentPixmapOnShadowDisplay: XCreateImage failed.\n"); + #endif + + if (data != NULL) + { + xfree(data); + } + + return False; + } + + value.foreground = 0xff0000; + value.background = 0x000000; + value.plane_mask = 0xffffff; + value.fill_style = FillSolid; + + gc = XCreateGC(shadow, win, GCBackground | + GCForeground | GCFillStyle | GCPlaneMask, &value); + + NXCleanImage(image); + + XPutImage(shadow, win, gc, image, 0, 0, 0, 0, width, height); + + XFreeGC(shadow, gc); + + if (image != NULL) + { + XDestroyImage(image); + } + + return True; +} + +Bool nxagentFbOnShadowDisplay() +{ + static Display *shadow; + static Window win; + static int init = True; + static int showTime; + static int prevWidth, prevHeight; + + XlibGC gc; + XGCValues value; + XImage *image; + Visual *pVisual; + WindowPtr pWin = WindowTable[0]; + unsigned int format; + int depth, width, height, length; + char *data = NULL; + + + if (pWin == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbOnShadowDisplay: The parent window is NULL.\n"); + #endif + + return False; + } + + depth = pWin -> drawable.depth; + width = pWin -> drawable.width; + height = pWin -> drawable.height; + format = (depth == 1) ? XYPixmap : ZPixmap; + + if (init) + { + shadow = XOpenDisplay("localhost:0"); + + if (shadow == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbOnShadowDisplay: WARNING! Shadow display not opened.\n"); + #endif + + return False; + } + + init = False; + + prevWidth = width; + prevHeight = height; + + win = XCreateSimpleWindow(shadow, DefaultRootWindow(shadow), 0, 0, + width, height, 0, 0xFFCC33, 0xFF); + + XMapWindow(shadow, win); + XClearWindow(shadow, win); + } + + if (DisplayPlanes(shadow, DefaultScreen(shadow)) != depth) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbOnShadowDisplay: Depths [%d - %d] are not equals!\n", + depth, DisplayPlanes(shadow, DefaultScreen(shadow))); + #endif + + return False; + } + + /* + * If the framebuffer is updated continuously, the nxagent + * visualization becomes too much slow. + */ + + if ((GetTimeInMillis() - showTime) < 500) + { + return False; + } + + showTime = GetTimeInMillis(); + + /* + * If the root window is resized, also the window on shadow + * display must be resized. + */ + + if (prevWidth != width || prevHeight != height) + { + XWindowChanges values; + + prevWidth = width; + prevHeight = height; + + values.width = width; + values.height = height; + XConfigureWindow(shadow, win, CWWidth | CWHeight, &values); + } + + length = nxagentImageLength(width, height, format, 0, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbOnShadowDisplay: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + return False; + } + + fbGetImage((DrawablePtr)pWin, 0, 0, + width, height, format, AllPlanes, data); + + pVisual = nxagentImageVisual((DrawablePtr) pWin, depth); + + if (pVisual == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbOnShadowDisplay: WARNING! Visual not found. Using default visual.\n"); + #endif + + pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual; + } + + image = XCreateImage(nxagentDisplay, pVisual, + depth, format, 0, (char *) data, + width, height, BitmapPad(nxagentDisplay), + nxagentImagePad(width, format, 0, depth)); + + if (image == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbOnShadowDisplay: XCreateImage failed.\n"); + #endif + + if (data) + { + xfree(data); + } + + return False; + } + + value.foreground = 0xff0000; + value.background = 0x000000; + value.plane_mask = 0xffffff; + value.fill_style = FillSolid; + + gc = XCreateGC(shadow, win, GCBackground | + GCForeground | GCFillStyle | GCPlaneMask, &value); + + NXCleanImage(image); + + XPutImage(shadow, win, gc, image, 0, 0, 0, 0, width, height); + + XFreeGC(shadow, gc); + + if (image != NULL) + { + XDestroyImage(image); + } + + return True; +} + +#endif + +#ifdef DEBUG + +void nxagentPrintResourceTypes() +{ + fprintf(stderr, "nxagentPrintResourceTypes: RT_PIXMAP [%lu].\n", (unsigned long) RT_PIXMAP); + fprintf(stderr, "nxagentPrintResourceTypes: RT_NX_PIXMAP [%lu].\n", (unsigned long) RT_NX_PIXMAP); + fprintf(stderr, "nxagentPrintResourceTypes: RT_GC [%lu].\n", (unsigned long) RT_GC); + fprintf(stderr, "nxagentPrintResourceTypes: RT_NX_GC [%lu].\n", (unsigned long) RT_NX_GC); + fprintf(stderr, "nxagentPrintResourceTypes: RT_FONT [%lu].\n", (unsigned long) RT_FONT); + fprintf(stderr, "nxagentPrintResourceTypes: RT_NX_FONT [%lu].\n", (unsigned long) RT_NX_FONT); + fprintf(stderr, "nxagentPrintResourceTypes: RT_CURSOR [%lu].\n", (unsigned long) RT_CURSOR); + fprintf(stderr, "nxagentPrintResourceTypes: RT_WINDOW [%lu].\n", (unsigned long) RT_WINDOW); + fprintf(stderr, "nxagentPrintResourceTypes: RT_COLORMAP [%lu].\n", (unsigned long) RT_COLORMAP); +} + +void nxagentPrintResourcePredicate(void *value, XID id, XID type, void *cdata) +{ + fprintf(stderr, "nxagentPrintResourcePredicate: Resource [%p] id [%lu] type [%lu].\n", + (void *) value, (unsigned long) id, (unsigned long) type); +} + +void nxagentPrintResources() +{ + Bool result; + int i; + + nxagentPrintResourceTypes(); + + for (i = 0; i < MAXCLIENTS; i++) + { + if (clients[i]) + { + fprintf(stderr, "nxagentPrintResources: Printing resources for client [%d]:\n", + i); + + FindAllClientResources(clients[i], nxagentPrintResourcePredicate, &result); + } + } +} + +#endif + + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h b/nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h new file mode 100644 index 000000000..5cf340d36 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Pixmap_H__ +#define __Pixmap_H__ + +#include "Split.h" + +extern RESTYPE RT_NX_PIXMAP; + +/* + * Pixmap privates structure. + */ + +typedef struct +{ + Pixmap id; + XID mid; + + Bool isVirtual; + Bool isShared; + + PixmapPtr pVirtualPixmap; + PixmapPtr pRealPixmap; + + void *pPicture; + + RegionPtr corruptedRegion; + + int corruptedBackground; + + int containGlyphs; + int containTrapezoids; + + int usageCounter; + + XID corruptedBackgroundId; + XID corruptedId; + + PixmapPtr synchronizationBitmap; + + Time corruptedTimestamp; + + SplitResourcePtr splitResource; + + int isBackingPixmap; + +} nxagentPrivPixmapRec; + +typedef nxagentPrivPixmapRec *nxagentPrivPixmapPtr; + +extern int nxagentPixmapPrivateIndex; + +/* + * Pixmap privates macro. + */ + +#define nxagentPixmapPriv(pPixmap) \ + ((nxagentPrivPixmapPtr)((pPixmap) -> devPrivates[nxagentPixmapPrivateIndex].ptr)) + +#define nxagentPixmap(pPixmap) (nxagentPixmapPriv(pPixmap) -> id) + +#define nxagentPixmapIsVirtual(pPixmap) \ + (nxagentPixmapPriv(pPixmap) -> isVirtual) + +#define nxagentIsShmPixmap(pPixmap) \ + (nxagentPixmapPriv(pPixmap) -> isShared) + +#define nxagentRealPixmap(pPixmap) \ + (nxagentPixmapPriv(pPixmap) -> pRealPixmap) + +#define nxagentVirtualPixmap(pPixmap) \ + (nxagentPixmapPriv(pPixmap) -> isVirtual ? pPixmap : \ + nxagentPixmapPriv(pPixmap) -> pVirtualPixmap) + +#define nxagentPixmapCorruptedRegion(pPixmap) \ + (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> corruptedRegion) + +#define nxagentPixmapContainGlyphs(pPixmap) \ + (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> containGlyphs) + +#define nxagentPixmapContainTrapezoids(pPixmap) \ + (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> containTrapezoids) + +#define nxagentIsCorruptedBackground(pPixmap) \ + (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> corruptedBackground) + +#define nxagentPixmapUsageCounter(pPixmap) \ + (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> usageCounter) + +#define nxagentPixmapTimestamp(pPixmap) \ + (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> corruptedTimestamp) + +PixmapPtr nxagentPixmapPtr(Pixmap pixmap); + +PixmapPtr nxagentCreatePixmap(ScreenPtr pScreen, int width, + int height, int depth); + +Bool nxagentDestroyPixmap(PixmapPtr pPixmap); + +RegionPtr nxagentPixmapToRegion(PixmapPtr pPixmap); + +Bool nxagentModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, + int bitsPerPixel, int devKind, pointer pPixData); + +RegionPtr nxagentCreateRegion(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int width, int height); + +void nxagentReconnectPixmap(void *p0, XID x1, void *p2); +Bool nxagentReconnectAllPixmaps(void *p0); +void nxagentDisconnectPixmap(void *p0, XID x1, void* p2); +Bool nxagentDisconnectAllPixmaps(void); + +int nxagentDestroyNewPixmapResourceType(pointer p, XID id); + +void nxagentSynchronizeShmPixmap(DrawablePtr pDrawable, int xPict, int yPict, + int wPict, int hPict); + +Bool nxagentPixmapOnShadowDisplay(PixmapPtr pMap); +Bool nxagentFbOnShadowDisplay(); + +#endif /* __Pixmap_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pointer.c b/nx-X11/programs/Xserver/hw/nxagent/Pointer.c new file mode 100644 index 000000000..f53dfbe52 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Pointer.c @@ -0,0 +1,157 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "X.h" +#include "Xproto.h" +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "mipointer.h" + +#include "Agent.h" +#include "Args.h" +#include "Display.h" +#include "Screen.h" +#include "Pointer.h" +#include "Events.h" +#include "Options.h" + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +void nxagentChangePointerControl(DeviceIntPtr pDev, PtrCtrl *ctrl) +{ + /* + * The original behaviour was to reset the pointer settings + * (acceleration and alas) to the default values. What the + * average user expects, on the contrary, is to have agent + * inheriting whatever value is set on the real X display. + * Having to reflect changes made inside the agent session, + * the correct behavior would be saving the original values + * and restoring them as soon as focus leaves the agent's + * window. + */ + + if (nxagentOption(DeviceControl) == True) + { + #ifdef TEST + fprintf(stderr, "nxagentChangePointerControl: WARNING! Propagating changes to pointer settings.\n"); + #endif + + XChangePointerControl(nxagentDisplay, True, True, + ctrl->num, ctrl->den, ctrl->threshold); + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentChangePointerControl: WARNING! Not propagating changes to pointer settings.\n"); + #endif +} + +int nxagentPointerProc(DeviceIntPtr pDev, int onoff) +{ + CARD8 map[MAXBUTTONS]; + int nmap; + int i; + + switch (onoff) + { + case DEVICE_INIT: + + #ifdef TEST + fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_INIT].\n"); + #endif + + if (NXDisplayError(nxagentDisplay) == 1) + { + return Success; + } + + nmap = XGetPointerMapping(nxagentDisplay, map, MAXBUTTONS); + for (i = 0; i <= nmap; i++) + map[i] = i; /* buttons are already mapped */ + InitPointerDeviceStruct((DevicePtr) pDev, map, nmap, + miPointerGetMotionEvents, + nxagentChangePointerControl, + miPointerGetMotionBufferSize()); + break; + case DEVICE_ON: + + #ifdef TEST + fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_ON].\n"); + #endif + + if (NXDisplayError(nxagentDisplay) == 1) + { + return Success; + } + + nxagentEnablePointerEvents(); + + break; + + case DEVICE_OFF: + + #ifdef TEST + fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_OFF].\n"); + #endif + + if (NXDisplayError(nxagentDisplay) == 1) + { + return Success; + } + + nxagentDisablePointerEvents(); + + break; + + case DEVICE_CLOSE: + + #ifdef TEST + fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_CLOSE].\n"); + #endif + + break; + } + + return Success; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pointer.h b/nx-X11/programs/Xserver/hw/nxagent/Pointer.h new file mode 100644 index 000000000..2adee6cb3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Pointer.h @@ -0,0 +1,45 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Pointer_H__ +#define __Pointer_H__ + +#define MAXBUTTONS 256 + +#define NXAGENT_POINTER_EVENT_MASK \ + (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ + EnterWindowMask | LeaveWindowMask) + +void nxagentChangePointerControl(DeviceIntPtr pDev, PtrCtrl *ctrl); + +int nxagentPointerProc(DeviceIntPtr pDev, int onoff); + +#endif /* __Pointer_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c new file mode 100644 index 000000000..de5f78fad --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c @@ -0,0 +1,788 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include + +#include "X.h" +#include "Xproto.h" +#include "Xpoll.h" +#include "mi.h" +#include "fb.h" +#include "inputstr.h" + +#include "Agent.h" +#include "Atoms.h" +#include "Drawable.h" +#include "Client.h" +#include "Reconnect.h" +#include "Display.h" +#include "Dialog.h" +#include "Screen.h" +#include "Windows.h" +#include "Events.h" +#include "Dialog.h" +#include "Args.h" +#include "Font.h" +#include "GCs.h" +#include "Trap.h" +#include "Keyboard.h" +#include "Composite.h" +#include "Millis.h" +#include "Splash.h" +#include "Error.h" + +#ifdef XKB +#include "XKBsrv.h" +#endif + +#include "NX.h" +#include "NXlib.h" +#include "NXalert.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#define NXAGENT_RECONNECT_DEFAULT_MESSAGE_SIZE 32 + +extern Bool nxagentReconnectAllCursor(void*); +extern Bool nxagentReconnectAllColormap(void*); +extern Bool nxagentReconnectAllWindows(void*); +extern Bool nxagentReconnectAllGlyphSet(void*); +extern Bool nxagentReconnectAllPictFormat(void*); +extern Bool nxagentReconnectAllPicture(void*); + +extern Bool nxagentDisconnectAllPicture(void); +extern Bool nxagentDisconnectAllWindows(void); +extern Bool nxagentDisconnectAllCursor(void); + +extern Bool nxagentReconnectFailedFonts(void*); +extern Bool nxagentInstallFontServerPath(void); +extern Bool nxagentUninstallFontServerPath(void); + +extern void nxagentRemoveXConnection(void); + +static char *nxagentGetReconnectError(void); + +void nxagentInitializeRecLossyLevel(void); + +static char *nxagentReconnectErrorMessage = NULL; +static int nxagentReconnectErrorId; + +extern Bool nxagentRenderEnable; + +extern char *nxagentKeyboard; + +enum SESSION_STATE nxagentSessionState = SESSION_STARTING; + +struct nxagentExceptionStruct nxagentException = {0, 0}; + +enum RECONNECTION_STEP +{ + DISPLAY_STEP = 0, + SCREEN_STEP, + FONT_STEP, + PIXMAP_STEP, + GC_STEP, + CURSOR_STEP, + COLORMAP_STEP, + WINDOW_STEP, + GLYPHSET_STEP, + PICTFORMAT_STEP, + PICTURE_STEP, + STEP_NONE +}; + +void *reconnectLossyLevel[STEP_NONE]; + +static enum RECONNECTION_STEP failedStep; + +int nxagentHandleConnectionStates(void) +{ + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Handling Exception with " + "state [%s] and transport [%d] and generation [%ld].\n", + DECODE_SESSION_STATE(nxagentSessionState), NXTransRunning(NX_FD_ANY), serverGeneration); + fprintf(stderr, "nxagentHandleConnectionStates: Entering with nxagentException.sigHup = [%d], " + "nxagentException.ioError = [%d]\n", + nxagentException.sigHup, nxagentException.ioError); + #endif + + if (nxagentException.sigHup > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Got SIGHUP in the exception flags.\n"); + #endif + + nxagentException.sigHup = 0; + + if (nxagentSessionState == SESSION_UP) + { + if (nxagentOption(Persistent)) + { + nxagentSessionState = SESSION_GOING_DOWN; + + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Handling " + "signal [SIGHUP] by disconnecting the agent.\n"); + + #endif + + } + else + { + nxagentTerminateSession(); + } + } + else if (nxagentSessionState == SESSION_STARTING) + { + nxagentTerminateSession(); + + #ifdef WARNING + fprintf(stderr, "nxagentHandleConnectionStates: Handling signal [SIGHUP] by terminating the agent.\n"); + #endif + } + else if (nxagentSessionState == SESSION_DOWN && + NXTransRunning(NX_FD_ANY) == 0) + { + nxagentSessionState = SESSION_GOING_UP; + + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Handling signal [SIGHUP] by reconnecting the agent.\n"); + #endif + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Handling signal with state [%s] and exception [%d].\n", + DECODE_SESSION_STATE(nxagentSessionState), dispatchException); + #endif + } + } + + if (nxagentNeedConnectionChange() == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Calling nxagentHandleConnectionChanges " + "with ioError [%d] sigHup [%d].\n", nxagentException.ioError, nxagentException.sigHup); + #endif + + nxagentHandleConnectionChanges(); + } + + if (nxagentException.ioError > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error in the exception flags.\n"); + #endif +/* +TODO: This should be reset only when + the state became SESSION_DOWN. +*/ + nxagentException.ioError = 0; + + if (nxagentOption(Persistent) == 1 && nxagentSessionState != SESSION_STARTING) + { + if (nxagentSessionState == SESSION_UP) + { + if ((dispatchException & DE_TERMINATE) == 0) + { + fprintf(stderr, "Session: Display failure detected at '%s'.\n", GetTimeAsString()); + + fprintf(stderr, "Session: Suspending session at '%s'.\n", GetTimeAsString()); + } + + nxagentDisconnectSession(); + } + else if (nxagentSessionState == SESSION_GOING_DOWN) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session " + "[SESSION_GOING_DOWN].\n"); + #endif + } + else if (nxagentSessionState == SESSION_GOING_UP) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session " + "[SESSION_GOING_UP].\n"); + #endif + + nxagentSessionState = SESSION_GOING_DOWN; + + nxagentSetReconnectError(FAILED_RESUME_DISPLAY_BROKEN_ALERT, + "Got I/O error during reconnect."); + + nxagentChangeOption(Fullscreen, False); + + return 1; + } + else if (nxagentSessionState == SESSION_DOWN) + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session " + "[SESSION_DOWN]. Ignoring.\n"); + #endif + + return 1; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session " + "[%d].\n", nxagentSessionState); + #endif + } + + nxagentSessionState = SESSION_DOWN; + + if ((dispatchException & DE_TERMINATE) == 0) + { + fprintf(stderr, "Session: Session suspended at '%s'.\n", GetTimeAsString()); + } + + nxagentResetDisplayHandlers(); + + return 1; + } + + fprintf(stderr, "Info: Disconnected from display '%s'.\n", nxagentDisplayName); + + nxagentTerminateSession(); + + return -1; + } + + return 0; +} + +void nxagentInitializeRecLossyLevel() +{ + *(int *)reconnectLossyLevel[DISPLAY_STEP] = 0; + *(int *)reconnectLossyLevel[SCREEN_STEP] = 0; + *(int *)reconnectLossyLevel[FONT_STEP] = 0; + *(int *)reconnectLossyLevel[PIXMAP_STEP] = 0; + *(int *)reconnectLossyLevel[GC_STEP] = 0; + *(int *)reconnectLossyLevel[CURSOR_STEP] = 0; + *(int *)reconnectLossyLevel[COLORMAP_STEP] = 0; + *(int *)reconnectLossyLevel[WINDOW_STEP] = 0; + *(int *)reconnectLossyLevel[GLYPHSET_STEP] = 0; + *(int *)reconnectLossyLevel[PICTFORMAT_STEP] = 0; + *(int *)reconnectLossyLevel[PICTURE_STEP] = 0; +} + +void nxagentInitReconnector(void) +{ + nxagentReconnectTrap = 0; + + reconnectLossyLevel[DISPLAY_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[SCREEN_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[FONT_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[PIXMAP_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[GC_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[CURSOR_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[COLORMAP_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[WINDOW_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[GLYPHSET_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[PICTFORMAT_STEP] = xalloc(sizeof(int)); + reconnectLossyLevel[PICTURE_STEP] = xalloc(sizeof(int)); +} + +void nxagentDisconnectSession(void) +{ + #ifdef TEST + fprintf(stderr, "nxagentDisconnectSession: Disconnecting session with state [%s].\n", + DECODE_SESSION_STATE(nxagentSessionState)); + #endif + + /* + * Force an I/O error on the display + * and wait until the NX transport + * is gone. + */ + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectSession: Disconnecting the X display.\n"); + #endif + + nxagentWaitDisplay(); + + /* + * Prepare for the next reconnection. + */ + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectSession: Disconnecting all X resources.\n"); + #endif + + nxagentInitializeRecLossyLevel(); + + nxagentBackupDisplayInfo(); + + if (nxagentOption(Rootless)) + { + nxagentFreePropertyList(); + } + + if (nxagentRenderEnable) + { + nxagentDisconnectAllPicture(); + } + + nxagentEmptyAllBackingStoreRegions(); + + nxagentDisconnectAllWindows(); + nxagentDisconnectAllCursor(); + nxagentDisconnectAllPixmaps(); + nxagentDisconnectAllGCs(); + nxagentDisconnectDisplay(); + + nxagentWMIsRunning = 0; + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectSession: Disconnection completed. SigHup is [%d]. IoError is [%d].\n", + nxagentException.sigHup, nxagentException.ioError); + #endif +} + +Bool nxagentReconnectSession(void) +{ + char *nxagentOldKeyboard = NULL; + + nxagentResizeDesktopAtStartup = False; + + /* + * The default is device settings have + * not to be propagated to the X server. + */ + + nxagentChangeOption(DeviceControl, False); + + /* + * We need to zero out every new XID + * created by the disconnected display. + */ + + nxagentDisconnectSession(); + + /* + * Set this in order to let the screen + * function to behave differently at + * reconnection time. + */ + + nxagentReconnectTrap = True; + + nxagentSetReconnectError(0, NULL); + + if (nxagentKeyboard != NULL) + { + int size; + + size = strlen(nxagentKeyboard); + + if ((nxagentOldKeyboard = xalloc(size + 1)) != NULL) + { + strncpy(nxagentOldKeyboard, nxagentKeyboard, size); + + nxagentOldKeyboard[size] = '\0'; + } + } + + if (nxagentKeyboard) + { + xfree(nxagentKeyboard); + + nxagentKeyboard = NULL; + } + + nxagentSaveOptions(); + + nxagentResetOptions(); + + nxagentProcessOptionsFile(); + + if (nxagentReconnectDisplay(reconnectLossyLevel[DISPLAY_STEP]) == 0) + { + failedStep = DISPLAY_STEP; + + #ifdef TEST + fprintf(stderr, "nxagentReconnect: WARNING! Failed display reconnection.\n"); + #endif + + goto nxagentReconnectError; + } + + if (nxagentReconnectScreen(reconnectLossyLevel[SCREEN_STEP]) == 0) + { + failedStep = SCREEN_STEP; + + goto nxagentReconnectError; + } + + nxagentDisconnectAllFonts(); + + nxagentListRemoteFonts("*", nxagentMaxFontNames); + + if (nxagentReconnectAllFonts(reconnectLossyLevel[FONT_STEP]) == 0) + { + if (nxagentReconnectFailedFonts(reconnectLossyLevel[FONT_STEP]) == 0) + { + failedStep = FONT_STEP; + + goto nxagentReconnectError; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnect: WARNING! Unable to retrieve all the fonts currently in use. " + "Missing fonts have been replaced.\n"); + #endif + + nxagentLaunchDialog(DIALOG_FONT_REPLACEMENT); + } + } + + /* + * Map the main window and send a + * SetSelectionOwner request to + * notify of the agent start. + */ + + nxagentMapDefaultWindows(); + + /* + * Ensure that the SetSelectionOwner + * request is sent through the link. + */ + + XFlush(nxagentDisplay); + + NXTransContinue(NULL); + + nxagentEmptyBSPixmapList(); + + if (nxagentReconnectAllPixmaps(reconnectLossyLevel[PIXMAP_STEP]) == 0) + { + failedStep = PIXMAP_STEP; + + goto nxagentReconnectError; + } + + if (nxagentReconnectAllGCs(reconnectLossyLevel[GC_STEP]) == 0) + { + failedStep = GC_STEP; + + goto nxagentReconnectError; + } + + if (nxagentReconnectAllColormap(reconnectLossyLevel[COLORMAP_STEP]) == 0) + { + failedStep = COLORMAP_STEP; + + goto nxagentReconnectError; + } + + if (nxagentReconnectAllWindows(reconnectLossyLevel[WINDOW_STEP]) == 0) + { + failedStep = WINDOW_STEP; + + goto nxagentReconnectError; + } + + if (nxagentRenderEnable) + { + if (nxagentReconnectAllGlyphSet(reconnectLossyLevel[GLYPHSET_STEP]) == 0) + { + failedStep = GLYPHSET_STEP; + + goto nxagentReconnectError; + } + + if (nxagentReconnectAllPictFormat(reconnectLossyLevel[PICTFORMAT_STEP]) == 0) + { + failedStep = PICTFORMAT_STEP; + + goto nxagentReconnectError; + } + + if (nxagentReconnectAllPicture(reconnectLossyLevel[PICTURE_STEP]) == 0) + { + failedStep = PICTURE_STEP; + + goto nxagentReconnectError; + } + } + + if (nxagentReconnectAllCursor(reconnectLossyLevel[CURSOR_STEP]) == 0) + { + failedStep = CURSOR_STEP; + + goto nxagentReconnectError; + } + + if (nxagentSetWindowCursors(reconnectLossyLevel[WINDOW_STEP]) == 0) + { + failedStep = WINDOW_STEP; + + goto nxagentReconnectError; + } + + if (nxagentOption(ResetKeyboardAtResume)) + { + if (nxagentKeyboard == NULL || nxagentOldKeyboard == NULL || + strcmp(nxagentKeyboard, nxagentOldKeyboard) != 0 || + strcmp(nxagentKeyboard, "query") == 0) + { + if (nxagentOldKeyboard != NULL) + { + xfree(nxagentOldKeyboard); + + nxagentOldKeyboard = NULL; + } + + if (nxagentResetKeyboard() == 0) + { + #ifdef WARNING + if (nxagentVerbose == 1) + { + fprintf(stderr, "nxagentReconnect: Failed to reset keyboard device.\n"); + } + #endif + + failedStep = WINDOW_STEP; + + goto nxagentReconnectError; + } + } + } + + nxagentDeactivatePointerGrab(); + + nxagentWakeupByReconnect(); + + nxagentFreeGCList(); + + nxagentRedirectDefaultWindows(); + + if (nxagentResizeDesktopAtStartup || nxagentOption(Rootless) == True) + { + nxagentRRSetScreenConfig(nxagentDefaultScreen, nxagentOption(RootWidth), nxagentOption(RootHeight)); + + nxagentResizeDesktopAtStartup = False; + } + + nxagentReconnectTrap = False; + + nxagentExposeArrayIsInitialized = False; + + if (nxagentSessionState != SESSION_GOING_UP) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnect: WARNING! Unexpected session state [%s] while reconnecting.\n", + DECODE_SESSION_STATE(nxagentSessionState)); + #endif + + goto nxagentReconnectError; + } + + fprintf(stderr, "Session: Session resumed at '%s'.\n", GetTimeAsString()); + + nxagentRemoveSplashWindow(NULL); + + /* + * We let the proxy flush the link on our behalf + * after having opened the display. We are now + * entering again the dispatcher so can flush + * the link explicitly. + */ + + #ifdef TEST + fprintf(stderr, "nxagentReconnect: Setting the NX flush policy to deferred.\n"); + #endif + + NXSetDisplayPolicy(nxagentDisplay, NXPolicyDeferred); + + nxagentCleanupBackupDisplayInfo(); + + return 1; + +nxagentReconnectError: + + if (failedStep == DISPLAY_STEP) + { + #ifdef TEST + fprintf(stderr, "nxagentReconnect: Reconnection failed in display step. Restoring options.\n"); + #endif + + nxagentRestoreOptions(); + } + else + { + nxagentCleanupBackupDisplayInfo(); + } + + if (*nxagentGetReconnectError() == '\0') + { + #ifdef WARNING + if (nxagentVerbose == 1) + { + fprintf(stderr, "nxagentReconnect: WARNING! The reconnect error message is not set. Failed step is [%d].\n", + failedStep); + } + #endif + + #ifdef TEST + fprintf(stderr, "nxagentReconnect: Reconnection failed due to a display error.\n"); + #endif + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentReconnect: Reconnection failed with reason '%s'\n", + nxagentGetReconnectError()); + #endif + } + + if (NXDisplayError(nxagentDisplay) == 0) + { + nxagentUnmapWindows(); + + nxagentFailedReconnectionDialog(nxagentReconnectErrorId, nxagentGetReconnectError()); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentReconnect: Cannot launch the dialog without a valid display.\n"); + } + #endif + + if (failedStep == FONT_STEP) + { + *((int *) reconnectLossyLevel[FONT_STEP]) = 1; + } + + if (nxagentDisplay == NULL) + { + nxagentDisconnectDisplay(); + } + + return 0; +} + +void nxagentSetReconnectError(int id, char *format, ...) +{ + static int size = 0; + + va_list ap; + int n; + + if (format == NULL) + { + nxagentSetReconnectError(id, ""); + + return; + } + + nxagentReconnectErrorId = id; + + while (1) + { + va_start (ap, format); + + n = vsnprintf(nxagentReconnectErrorMessage, size, format, ap); + + va_end(ap); + + if (n > -1 && n < size) + { + break; + } + if (n > -1) + { + size = n + 1; + } + else + { + /* + * The vsnprintf() in glibc 2.0.6 would return + * -1 when the output was truncated. See section + * NOTES on printf(3). + */ + + size = (size ? size * 2 : NXAGENT_RECONNECT_DEFAULT_MESSAGE_SIZE); + } + + nxagentReconnectErrorMessage = realloc(nxagentReconnectErrorMessage, size); + + if (nxagentReconnectErrorMessage == NULL) + { + FatalError("realloc failed"); + } + } + + return; +} + +static char* nxagentGetReconnectError() +{ + if (nxagentReconnectErrorMessage == NULL) + { + nxagentSetReconnectError(nxagentReconnectErrorId, ""); + } + + return nxagentReconnectErrorMessage; +} + +void nxagentHandleConnectionChanges() +{ + #ifdef TEST + fprintf(stderr, "nxagentHandleConnectionChanges: Called.\n"); + #endif + + if (nxagentSessionState == SESSION_GOING_DOWN) + { + fprintf(stderr, "Session: Suspending session at '%s'.\n", GetTimeAsString()); + + nxagentDisconnectSession(); + } + else if (nxagentSessionState == SESSION_GOING_UP) + { + fprintf(stderr, "Session: Resuming session at '%s'.\n", GetTimeAsString()); + + if (nxagentReconnectSession()) + { + nxagentSessionState = SESSION_UP; + } + else + { + nxagentSessionState = SESSION_GOING_DOWN; + + fprintf(stderr, "Session: Display failure detected at '%s'.\n", GetTimeAsString()); + + fprintf(stderr, "Session: Suspending session at '%s'.\n", GetTimeAsString()); + + nxagentDisconnectSession(); + } + } +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Reconnect.h b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.h new file mode 100644 index 000000000..0a2a8a6a7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.h @@ -0,0 +1,68 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Reconnect_H__ +#define __Reconnect_H__ + +extern Display *nxagentDisplayState; + +struct nxagentExceptionStruct +{ + int sigHup; + int ioError; +}; + +extern struct nxagentExceptionStruct nxagentException; + +void nxagentSetReconnectError(int id, char *format, ...); + +void nxagentInitReconnector(void); +Bool nxagentReconnectSession(void); +int nxagentHandleConnectionStates(void); +void nxagentHandleConnectionChanges(void); + +enum SESSION_STATE +{ + SESSION_STARTING, + SESSION_UP, + SESSION_DOWN, + SESSION_GOING_DOWN, + SESSION_GOING_UP +}; + +extern enum SESSION_STATE nxagentSessionState; + +#define DECODE_SESSION_STATE(state) \ + ((state) == SESSION_STARTING ? "SESSION_STARTING" : \ + (state) == SESSION_UP ? "SESSION_UP" : \ + (state) == SESSION_GOING_UP? "SESSION_GOING_UP" : \ + (state) == SESSION_DOWN ? "SESSION_DOWN" : \ + (state) == SESSION_GOING_DOWN? "SESSION_GOING_DOWN" : \ + "UNKNOWN") + +/* + * Use this macro in the block and wakeup + * handlers to save a function call. + */ + +#define nxagentNeedConnectionChange() \ + (nxagentSessionState == SESSION_GOING_DOWN || \ + nxagentSessionState == SESSION_GOING_UP) + +void nxagentDisconnectSession(void); + +#endif /* __Reconnect_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Render.c b/nx-X11/programs/Xserver/hw/nxagent/Render.c new file mode 100644 index 000000000..b1ff219e7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Render.c @@ -0,0 +1,2810 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "NXpicturestr.h" +#include "NXglyphstr.h" + +#include "Render.h" + +#include "X.h" +#include "Xproto.h" + +#include "render.h" +#include "renderproto.h" + +#include "mi.h" +#include "fb.h" +#include "mipict.h" +#include "fbpict.h" +#include "dixstruct.h" + +#include "Agent.h" +#include "Drawable.h" +#include "Trap.h" +#include "Args.h" + +#define Atom XlibAtom +#define Pixmap XlibPixmap +#include "../../../../lib/Xrender/Xrenderint.h" +#undef Atom +#undef Pixmap + +#include "region.h" +#include "extutil.h" + +#include "Display.h" +#include "Pixmaps.h" +#include "Cursor.h" +#include "Client.h" +#include "Image.h" +#include "Pixels.h" +#include "Handlers.h" + +#include "NXproto.h" + +#define MAX_FORMATS 255 + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +/* + * Define if you want split multiple glyph lists + * into multiple RenderCompositeGlyphs requests. + */ + +#undef SPLIT_GLYPH_LISTS + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* +FIXME: Most operations don't seem to produce any visible result + but still generate tons of traffic. +*/ +#undef SKIP_LOUSY_RENDER_OPERATIONS +#undef SKIP_REALLY_ALL_LOUSY_RENDER_OPERATIONS + +/* + * Do we split the big trapezoid requests? + */ + +#define TRAPEZOIDS_PER_REQUEST 256 + +/* + * Margin added around the glyphs extent (in pixels). + */ + +#define GLYPH_BOX_MARGIN 2 + +int nxagentRenderEnable = UNDEFINED; +int nxagentRenderVersionMajor; +int nxagentRenderVersionMinor; + +int nxagentPicturePrivateIndex = 0; + +#ifndef NXAGENT_UPGRADE +static int picturePrivateCount = 0; +#endif + +static int nxagentNumFormats = 0; + +static XRenderPictFormat nxagentArrayFormats[MAX_FORMATS]; + +XRenderPictFormat *nxagentMatchingFormats(PictFormatPtr pForm); + +BoxPtr nxagentGlyphsExtents; +BoxPtr nxagentTrapezoidExtents; + +#ifdef DEBUG + +static void nxagentPrintFormat(XRenderPictFormat *pFormat); + +#endif + +/* + * From NXglyph.c. + */ + +extern const CARD8 glyphDepths[]; + +/* + * From NXdispatch.c. + */ + +extern void BitOrderInvert(unsigned char *data, int nbytes); + +/* + * Other functions defined here. + */ + +void nxagentQueryFormats(void); + +void nxagentCreateGlyphSet(GlyphSetPtr pGly); + +int nxagentCursorSaveRenderInfo(ScreenPtr pScreen, CursorPtr pCursor); + +void nxagentCursorPostSaveRenderInfo(CursorPtr pCursor, ScreenPtr pScreen, + PicturePtr pPicture, int x, int y); + +int nxagentCreatePicture(PicturePtr pPicture, Mask mask); + +void nxagentDestroyPicture(PicturePtr pPicture); + +int nxagentChangePictureClip(PicturePtr pPicture, int clipType, int nRects, + xRectangle *rects, int xOrigin, int yOrigin); + +void nxagentDestroyPictureClip(PicturePtr pPicture); + +void nxagentValidatePicture(PicturePtr pPicture, Mask mask); + +void nxagentComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height); + +void nxagentGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists, + XGlyphElt8 *elts, int sizeID, GlyphPtr *glyphsBase); + +void nxagentCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, + int nRect, xRectangle *rects); + +void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps); + +void nxagentRasterizeTrapezoid(PicturePtr pMask, xTrapezoid *trap, + int x_off, int y_off); + +void nxagentTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle *tris); + +void nxagentTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed *points); + +void nxagentChangePicture(PicturePtr pPicture, Mask mask); + +void nxagentTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed *points); + +void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet); + +void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph); + +void nxagentFreeGlyphSet(GlyphSetPtr glyphSet); + +void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform); + +void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size, + pointer params, int nparams); + +Bool nxagentReconnectAllGlyphSet(void *p); + +Bool nxagentReconnectAllPicture(void *); + +Bool nxagentDisconnectAllPicture(void); + +void nxagentRenderExtensionInit() +{ + int first_event, first_error; + int major_version, minor_version; + + if (XRenderQueryExtension(nxagentDisplay, &first_event, &first_error)) + { + XRenderQueryVersion(nxagentDisplay, &major_version, &minor_version); + + /* + * As the RENDER requests are passed directly to + * the remote X server this can cause problems if + * our RENDER version is different from the version + * supported by the remote. For this reasos let's + * advertise to our clients the lowest between the + + two versions. + */ + + if (major_version > RENDER_MAJOR || + (major_version == RENDER_MAJOR && + minor_version > RENDER_MINOR)) + { + #ifdef TEST + fprintf(stderr, "nxagentRenderExtensionInit: Using render version [%d.%d] with " + "remote version [%d.%d].\n", RENDER_MAJOR, RENDER_MINOR, + major_version, minor_version); + #endif + + nxagentRenderVersionMajor = RENDER_MAJOR; + nxagentRenderVersionMinor = RENDER_MINOR; + } + else if (major_version < RENDER_MAJOR || + (major_version == RENDER_MAJOR && + minor_version < RENDER_MINOR)) + { + #ifdef TEST + fprintf(stderr, "Info: Local render version %d.%d is higher " + "than remote version %d.%d.\n", RENDER_MAJOR, RENDER_MINOR, + major_version, minor_version); + + fprintf(stderr, "Info: Lowering the render version reported to clients.\n"); + #endif + + nxagentRenderVersionMajor = major_version; + nxagentRenderVersionMinor = minor_version; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentRenderExtensionInit: Local render version %d.%d " + "matches remote version %d.%d.\n", RENDER_MAJOR, RENDER_MINOR, + major_version, minor_version); + #endif + + nxagentRenderVersionMajor = major_version; + nxagentRenderVersionMinor = minor_version; + } + } + else + { + #ifdef WARNING + fprintf(stderr, "Warning: Render not available on the remote display.\n"); + #endif + + nxagentRenderEnable = False; + } +} + +int nxagentCursorSaveRenderInfo(ScreenPtr pScreen, CursorPtr pCursor) +{ + pCursor -> devPriv[pScreen -> myNum] = xalloc(sizeof(nxagentPrivCursor)); + + if (nxagentCursorPriv(pCursor, pScreen) == NULL) + { + FatalError("xalloc failed"); + } + + nxagentCursorUsesRender(pCursor, pScreen) = 1; + nxagentCursorPicture(pCursor, pScreen) = NULL; + + return 1; +} + +void nxagentCursorPostSaveRenderInfo(CursorPtr pCursor, ScreenPtr pScreen, + PicturePtr pPicture, int x, int y) +{ + nxagentCursorPicture(pCursor, pScreen) = pPicture; + nxagentCursorXOffset(pCursor, pScreen) = x; + nxagentCursorYOffset(pCursor, pScreen) = y; +} + +int nxagentRenderRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + int cid; + int x, y; + + PicturePtr pPicture; + + pPicture = nxagentCursorPicture(pCursor, pScreen); + + pPicture -> refcnt++; + + x = nxagentCursorXOffset(pCursor, pScreen); + y = nxagentCursorYOffset(pCursor, pScreen); + + /* + * Set the lossless trap so that the image functions + * will not try to encode the image using a lossy + * compression. Drawables should have a quality flag, + * telling if they were originally encoded with a + * lossy algorithm. This would allow us to skip the + * synchronization if the cursor was already encoded + * with the best quality. + */ + + #ifdef TEST + fprintf(stderr, "nxagentRenderRealizeCursor: Forcing the synchronization " + "of the cursor.\n"); + #endif + + nxagentMarkCorruptedRegion(pPicture -> pDrawable, NULL); + + nxagentLosslessTrap = 1; + + nxagentSynchronizeDrawable(pPicture -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + + nxagentLosslessTrap = 0; + + cid = XRenderCreateCursor(nxagentDisplay, nxagentPicture(pPicture), x, y); + + nxagentCursor(pCursor, pScreen) = cid; + + return 1; +} + +int nxagentCreatePicture(PicturePtr pPicture, Mask mask) +{ + XRenderPictureAttributes attributes; + unsigned long valuemask=0; + XRenderPictFormat *pForm; + + Picture id; + + #ifdef DEBUG + fprintf(stderr, "nxagentCreatePicture: Function called with picture at [%p] and mask [%ld].\n", + (void *) pPicture, mask); + #endif + + if (pPicture == NULL) + { + return 0; + } + + #ifdef DEBUG + + if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP) + { + if (nxagentIsShmPixmap((PixmapPtr)pPicture -> pDrawable)) + { + fprintf (stderr, "nxagentCreatePicture: Picture uses a shared pixmap.\n"); + } + else + { + fprintf (stderr, "nxagentCreatePicture: Picture uses a plain pixmap.\n"); + } + } + else + { + fprintf (stderr, "nxagentCreatePicture: Picture uses a window.\n"); + } + + #endif + + /* + * All the picture default values are 0. + */ + + memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0, sizeof(XRenderPictureAttributes)); + + if (mask & CPRepeat) + { + attributes.repeat = (Bool)pPicture -> repeat; + + valuemask |= CPRepeat; + + nxagentSetPictureRemoteValue(pPicture, repeat, attributes.repeat); + } + + if (mask & CPAlphaMap) + { + attributes.alpha_map = nxagentPicturePriv(pPicture -> alphaMap) -> picture; + + valuemask |= CPAlphaMap; + + nxagentSetPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map); + } + + if (mask & CPAlphaXOrigin) + { + attributes.alpha_x_origin = pPicture -> alphaOrigin.x; + + valuemask |= CPAlphaXOrigin; + + nxagentSetPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin); + } + + if (mask & CPAlphaYOrigin) + { + attributes.alpha_y_origin = pPicture -> alphaOrigin.y; + + valuemask |= CPAlphaYOrigin; + + nxagentSetPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin); + } + + if (mask & CPClipXOrigin) + { + attributes.clip_x_origin = pPicture -> clipOrigin.x; + + valuemask |= CPClipXOrigin; + + nxagentSetPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin); + } + + if (mask & CPClipYOrigin) + { + attributes.clip_y_origin = pPicture -> clipOrigin.y; + + valuemask |= CPClipYOrigin; + + nxagentSetPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin); + } + + if (mask & CPGraphicsExposure) + { + attributes.graphics_exposures = (Bool)pPicture -> graphicsExposures; + + valuemask |= CPGraphicsExposure; + + nxagentSetPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures); + } + + if (mask & CPSubwindowMode) + { + attributes.subwindow_mode = pPicture -> subWindowMode; + + valuemask |= CPSubwindowMode; + + nxagentSetPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode); + } + + if (mask & CPClipMask) + { + attributes.clip_mask = None; + + valuemask |= CPClipMask; + + nxagentSetPictureRemoteValue(pPicture, clip_mask, attributes.clip_mask); + } + + if (mask & CPPolyEdge) + { + attributes.poly_edge = pPicture -> polyEdge; + + valuemask |= CPPolyEdge; + + nxagentSetPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge); + } + + if (mask & CPPolyMode) + { + attributes.poly_mode = pPicture -> polyMode; + + valuemask |= CPPolyMode; + + nxagentSetPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode); + } + + if (mask & CPDither) + { + attributes.dither = pPicture -> dither; + + valuemask |= CPDither; + + nxagentSetPictureRemoteValue(pPicture, dither, attributes.dither); + } + + if (mask & CPComponentAlpha) + { + attributes.component_alpha = pPicture -> componentAlpha; + + valuemask |= CPComponentAlpha; + + nxagentSetPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha); + } + + pForm = NULL; + + if (pPicture -> pFormat != NULL) + { + pForm = nxagentMatchingFormats(pPicture -> pFormat); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + } + + if (pForm == NULL) + { + fprintf(stderr, "nxagentCreatePicture: WARNING! The requested format was not found.\n"); + + return 0; + } + + id = XRenderCreatePicture(nxagentDisplay, + nxagentDrawable(pPicture -> pDrawable), + pForm, + valuemask, + &attributes); + + #ifdef TEST + fprintf(stderr, "nxagentCreatePicture: Created picture at [%p] with drawable at [%p].\n", + (void *) pPicture, (void *) pPicture -> pDrawable); + #endif + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif + + nxagentPicturePriv(pPicture) -> picture = id; + + if (nxagentAlphaEnabled == 1 && pPicture -> pDrawable->depth == 32 && + pPicture -> pFormat -> direct.alpha != 0) + { + if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pPicture -> pDrawable)) -> pPicture = pPicture; + } + else if (pPicture -> pDrawable -> type == DRAWABLE_WINDOW) + { + nxagentWindowPriv((WindowPtr) pPicture -> pDrawable) -> pPicture = pPicture; + } + } + + return 1; +} + +XRenderPictFormat *nxagentMatchingFormats(PictFormatPtr pFormat) +{ + int i; + + for (i = 0; i < nxagentNumFormats; i++) + { + if (pFormat -> type == nxagentArrayFormats[i].type && + pFormat -> depth == nxagentArrayFormats[i].depth && + pFormat -> direct.red == nxagentArrayFormats[i].direct.red && + pFormat -> direct.green == nxagentArrayFormats[i].direct.green && + pFormat -> direct.blue == nxagentArrayFormats[i].direct.blue && + pFormat -> direct.redMask == nxagentArrayFormats[i].direct.redMask && + pFormat -> direct.greenMask == nxagentArrayFormats[i].direct.greenMask && + pFormat -> direct.blueMask == nxagentArrayFormats[i].direct.blueMask && + pFormat -> direct.alpha == nxagentArrayFormats[i].direct.alpha && + pFormat -> direct.alphaMask == nxagentArrayFormats[i].direct.alphaMask) + { + return &nxagentArrayFormats[i]; + } + } + + #ifdef DEBUG + fprintf(stderr, "nxagentMatchingFormats: The requested format was not found.\n"); + #endif + + return NULL; +} + +void nxagentDestroyPicture(PicturePtr pPicture) +{ + #ifdef TEST + fprintf(stderr, "nxagentDestroyPicture: Going to destroy picture at [%p].\n", + (void *) pPicture); + #endif + + if (pPicture == NULL) + { + return; + } + + XRenderFreePicture(nxagentDisplay, + nxagentPicturePriv(pPicture) -> picture); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +int nxagentChangePictureClip(PicturePtr pPicture, int clipType, int nRects, + xRectangle *rects, int xOrigin, int yOrigin) +{ + #ifdef TEST + fprintf(stderr, "nxagentChangePictureClip: Going to change clip of picture at [%p].\n", + (void *) pPicture); + #endif + + #ifdef DEBUG + fprintf(stderr, "nxagentChangePictureClip: clipType [%d] nRects [%d] xRectangle [%p] " + "xOrigin [%d] yOrigin [%d].\n", clipType, nRects, (void *) rects, xOrigin, yOrigin); + #endif + + if (pPicture == NULL) + { + return 0; + } + + switch (clipType) + { + case CT_PIXMAP: + { + #ifdef DEBUG + fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_PIXMAP].\n"); + #endif + + /* + * if(!nRects) + * { + * return 0; + * } + */ +/* +FIXME: Is this useful or just a waste of bandwidth? + + Apparently useless with QT. +*/ + #ifndef SKIP_LOUSY_RENDER_OPERATIONS + + XRenderSetPictureClipRectangles(nxagentDisplay, + nxagentPicturePriv(pPicture) -> picture, + xOrigin, + yOrigin, + (XRectangle*)rects, + nRects); + + nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin); + nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin); + nxagentSetPictureRemoteValue(pPicture, clip_mask, 1); + + #endif + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif + + break; + } + case CT_NONE: + { + #ifdef DEBUG + fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_NONE].\n"); + #endif +/* +FIXME: Is this useful or just a waste of bandwidth? + + Apparently useless with QT. +*/ + #ifndef SKIP_LOUSY_RENDER_OPERATIONS + + XRenderSetPictureClipRectangles(nxagentDisplay, + nxagentPicturePriv(pPicture) -> picture, + xOrigin, + yOrigin, + (XRectangle*)rects, + nRects); + + nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin); + nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin); + nxagentSetPictureRemoteValue(pPicture, clip_mask, 1); + + #endif + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif + + break; + } + case CT_REGION: + { + Region reg; + XRectangle rectangle; + int index; + + #ifdef DEBUG + fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_REGION].\n"); + #endif + + reg = XCreateRegion(); + + for (index = 0; index <= nRects; index++, rects++) + { + rectangle.x = rects -> x; + rectangle.y = rects -> y; + rectangle.width = rects -> width; + rectangle.height = rects -> height; + + XUnionRectWithRegion(&rectangle, reg, reg); + } +/* +FIXME: Is this useful or just a waste of bandwidth? + + Apparently useless with QT. +*/ + #ifndef SKIP_LOUSY_RENDER_OPERATIONS + + XRenderSetPictureClipRegion(nxagentDisplay, + nxagentPicturePriv(pPicture) -> picture, + reg); + + nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin); + nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin); + nxagentSetPictureRemoteValue(pPicture, clip_mask, 1); + + #endif + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif + + XDestroyRegion(reg); + + break; + } + default: + { + #ifdef DEBUG + fprintf(stderr, "nxagentChangePictureClip: clipType not found\n"); + #endif + + break; + } + } + + return 1; +} + +void nxagentDestroyPictureClip(PicturePtr pPicture) +{ + #ifdef DEBUG + fprintf(stderr, "nxagentDestroyPictureClip: Nothing to do.\n"); + #endif +} + +void nxagentChangePicture(PicturePtr pPicture, Mask mask) +{ + XRenderPictureAttributes attributes; + unsigned long valuemask = 0; + + #ifdef DEBUG + fprintf(stderr, "nxagentChangePicture: Going to change picture at [%p] with mask [%ld].\n", + (void *) pPicture, mask); + #endif + + if (pPicture == NULL) + { + return; + } + + if (mask & CPRepeat) + { + attributes.repeat = (Bool)pPicture -> repeat; + + if (nxagentCheckPictureRemoteValue(pPicture, repeat, attributes.repeat) == 0) + { + valuemask |= CPRepeat; + + nxagentSetPictureRemoteValue(pPicture, repeat, attributes.repeat); + } + } + + if (mask & CPAlphaMap) + { + attributes.alpha_map = nxagentPicturePriv(pPicture -> alphaMap) -> picture; + + if (nxagentCheckPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map) == 0) + { + valuemask |= CPAlphaMap; + + nxagentSetPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map); + } + } + + if (mask & CPAlphaXOrigin) + { + attributes.alpha_x_origin = pPicture -> alphaOrigin.x; + + if (nxagentCheckPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin) == 0) + { + valuemask |= CPAlphaXOrigin; + + nxagentSetPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin); + } + } + + if (mask & CPAlphaYOrigin) + { + attributes.alpha_y_origin = pPicture -> alphaOrigin.y; + + if (nxagentCheckPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin) == 0) + { + valuemask |= CPAlphaYOrigin; + + nxagentSetPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin); + } + } + + if (mask & CPClipXOrigin) + { + attributes.clip_x_origin = pPicture -> clipOrigin.x; + + if (nxagentCheckPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin) == 0) + { + valuemask |= CPClipXOrigin; + + nxagentSetPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin); + } + } + + if (mask & CPClipYOrigin) + { + attributes.clip_y_origin = pPicture -> clipOrigin.y; + + if (nxagentCheckPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin) == 0) + { + valuemask |= CPClipYOrigin; + + nxagentSetPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin); + } + } + + if (mask & CPGraphicsExposure) + { + attributes.graphics_exposures = (Bool)pPicture -> graphicsExposures; + + if (nxagentCheckPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures) == 0) + { + valuemask |= CPGraphicsExposure; + + nxagentSetPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures); + } + } + + if (mask & CPSubwindowMode) + { + attributes.subwindow_mode = pPicture -> subWindowMode; + + if (nxagentCheckPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode) == 0) + { + valuemask |= CPSubwindowMode; + + nxagentSetPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode); + } + } + + if (mask & CPClipMask) + { + attributes.clip_mask = None; + + /* + * The nxagent doesn't know the remote id of + * the picture's clip mask, so the clip_mask + * value is used as a boolean: it is set to 0 + * when the clip_mask is None, otherwise it is + * 1. + */ + + if (nxagentPicturePriv(pPicture) -> lastServerValues.clip_mask != 0) + { + valuemask |= CPClipMask; + + nxagentSetPictureRemoteValue(pPicture, clip_mask, 0); + } + } + + if (mask & CPPolyEdge) + { + attributes.poly_edge = pPicture -> polyEdge; + + if (nxagentCheckPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge) == 0) + { + valuemask |= CPPolyEdge; + + nxagentSetPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge); + } + } + + if (mask & CPPolyMode) + { + attributes.poly_mode = pPicture -> polyMode; + + if (nxagentCheckPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode) == 0) + { + valuemask |= CPPolyMode; + + nxagentSetPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode); + } + } + + if (mask & CPDither) + { + attributes.dither = pPicture -> dither; + + if (nxagentCheckPictureRemoteValue(pPicture, dither, attributes.dither) == 0) + { + valuemask |= CPDither; + + nxagentSetPictureRemoteValue(pPicture, dither, attributes.dither); + } + } + + if (mask & CPComponentAlpha) + { + attributes.component_alpha = pPicture -> componentAlpha; + + if (nxagentCheckPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha) == 0) + { + valuemask |= CPComponentAlpha; + + nxagentSetPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha); + } + } + + #ifdef TEST + + if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP) + { + fprintf(stderr, "nxagentChangePicture: %sPixmap [%p] Picture [%p][%p].\n", + nxagentIsShmPixmap((PixmapPtr)pPicture -> pDrawable) ? "Shared " : "", + (void *) pPicture -> pDrawable, (void *) nxagentPicturePriv(pPicture) -> picture, + (void *) pPicture); + } + + #endif +/* +FIXME: Is this useful or just a waste of bandwidth? + + Apparently useless with QT. + + Without this the text is not rendered on GTK/Cairo. +*/ + #ifndef SKIP_REALLY_ALL_LOUSY_RENDER_OPERATIONS + + if (valuemask != 0) + { + XRenderChangePicture(nxagentDisplay, + nxagentPicturePriv(pPicture) -> picture, + valuemask, + &attributes); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentChangePicture: Skipping change of picture [%p] on remote X server.\n", + (void *) pPicture); + } + #endif + + #endif + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentValidatePicture(PicturePtr pPicture, Mask mask) +{ + #ifdef DEBUG + fprintf(stderr, "nxagentValidatePicture: Nothing to do.\n"); + #endif +} + +void nxagentComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, + INT16 yDst, CARD16 width, CARD16 height) +{ + RegionPtr pDstRegion; + + if (pSrc == NULL || pDst == NULL) + { + return; + } + + #ifdef DEBUG + + fprintf(stderr, "nxagentComposite: Source Picture [%lu][%p] with drawable [%s%s][%p].\n", + nxagentPicturePriv(pSrc) -> picture, (void *) pSrc, + (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pSrc -> pDrawable)) ? "Shared " : "", + pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window", + (void *) pSrc -> pDrawable); + + fprintf(stderr, "nxagentComposite: Destination Picture [%lu][%p] with drawable [%s%s][%p].\n", + nxagentPicturePriv(pDst) -> picture, (void *) pDst, + (pDst -> pDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pDst -> pDrawable)) ? "Shared " : "", + pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window", + (void *) pDst -> pDrawable); + + if (pMask) + { + fprintf(stderr, "nxagentComposite: Mask Picture [%lu][%p] with drawable [%s%s][%p].\n", + nxagentPicturePriv(pMask) -> picture, (void *) pMask, + (pMask -> pDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pMask -> pDrawable)) ? "Shared " : "", + pMask -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window", + (void *) pMask -> pDrawable); + } + + #endif + + if (NXAGENT_SHOULD_DEFER_COMPOSITE(pSrc, pMask, pDst)) + { + pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, xDst, yDst, width, height); + + #ifdef TEST + fprintf(stderr, "nxagentComposite: WARNING! Prevented operation on region [%d,%d,%d,%d] " + "for drawable at [%p] with type [%s].\n", pDstRegion -> extents.x1, + pDstRegion -> extents.y1, pDstRegion -> extents.x2, pDstRegion -> extents.y2, + (void *) pDst -> pDrawable, + pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"); + + #endif + + nxagentMarkCorruptedRegion(pDst -> pDrawable, pDstRegion); + + nxagentFreeRegion(pDst -> pDrawable, pDstRegion); + + return; + } + + /* + * Synchronize the content of the shared memory pixmap + * but pay attention at not doing this more than once. + * We need to wait until the image data has been recom- + * posed at the X server side or the operation will use + * the wrong data. + */ + + nxagentSynchronizeShmPixmap(pSrc -> pDrawable, xSrc, ySrc, width, height); + + if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentComposite: Synchronizing the source drawable [%p].\n", + (void *) pSrc -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + + if (pDst -> pDrawable != pSrc -> pDrawable) + { + nxagentSynchronizeShmPixmap(pDst -> pDrawable, xDst, yDst, width, height); + + if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentComposite: Synchronizing the destination drawable [%p].\n", + (void *) pDst -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + } + + if (pMask != NULL && pMask -> pDrawable != pSrc -> pDrawable && + pMask -> pDrawable != pDst -> pDrawable) + { + nxagentSynchronizeShmPixmap(pMask -> pDrawable, xMask, yMask, width, height); + + if (nxagentDrawableStatus(pMask -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentComposite: Synchronizing the mask drawable [%p].\n", + (void *) pMask -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pMask -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + } + + /* + * The glyphs flag have to be propagated between + * drawables, in order to avoid to encode the + * text with lossy algorithms (like JPEG). Unlu- + * ckily we have verified that if the render com- + * posite propagates the flag, the deferring of + * render trapezoids doesn't work well. Moreover, + * by commenting out this code we have not noticed + * any visual problems. + * + * if (nxagentDrawableContainGlyphs(pSrc -> pDrawable) == 1) + * { + * nxagentSetDrawableContainGlyphs(pDst -> pDrawable, 1); + * } + */ + + XRenderComposite(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + pMask ? nxagentPicturePriv(pMask) -> picture : 0, + nxagentPicturePriv(pDst) -> picture, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists, + XGlyphElt8 *elts, int sizeID, GlyphPtr *glyphsBase) +{ + XRenderPictFormat *pForm; + + BoxRec glyphBox; + + XGlyphElt8 *elements; + + #ifdef SPLIT_GLYPH_LISTS + + GlyphPtr glyph; + + int x; + int y; + int i; + int j; + + #endif /* #ifdef SPLIT_GLYPH_LISTS */ + + if (pSrc == NULL || pDst == NULL) + { + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: Called with source [%s][%p] destination [%s][%p] and size id [%d].\n", + (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pSrc, + (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pDst, + sizeID); + #endif + + pForm = NULL; + + if (maskFormat != NULL) + { + pForm = nxagentMatchingFormats(maskFormat); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + + if (pForm == NULL) + { + return; + } + } + + if (nxagentGlyphsExtents != NullBox) + { + glyphBox.x1 = nxagentGlyphsExtents -> x1; + glyphBox.y1 = nxagentGlyphsExtents -> y1; + glyphBox.x2 = nxagentGlyphsExtents -> x2; + glyphBox.y2 = nxagentGlyphsExtents -> y2; + + /* + * By extending the glyph extents the + * visual aspect looks nicer because + * the synchronized region is not glued + * to the fonts. + */ + + if (glyphBox.x2 != glyphBox.x1) + { + glyphBox.x1 -= GLYPH_BOX_MARGIN; + glyphBox.x2 += GLYPH_BOX_MARGIN; + } + + if (glyphBox.y2 != glyphBox.y1) + { + glyphBox.y1 -= GLYPH_BOX_MARGIN; + glyphBox.y2 += GLYPH_BOX_MARGIN; + } + } + + /* + * If the destination window is hidden, the + * operation can be prevented. + */ + + if (pDst -> pDrawable -> type == DRAWABLE_WINDOW) + { + RegionPtr pRegion; + + pRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, glyphBox.x1, glyphBox.y1, + glyphBox.x2 - glyphBox.x1, glyphBox.y2 - glyphBox.y1); + + if (REGION_NIL(pRegion) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: WARNING! Glyphs prevented on hidden window at [%p].\n", + (void *) pDst -> pDrawable); + #endif + + nxagentFreeRegion(pDst -> pDrawable, pRegion); + + return; + } + + nxagentFreeRegion(pDst -> pDrawable, pRegion); + } + + /* + * Need to synchronize the pixmaps involved in + * the operation before rendering the glyphs + * on the real X server. + */ + + if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: Synchronizing source [%s] at [%p].\n", + pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window", + (void *) pSrc -> pDrawable); + #endif + + /* + * If the source drawable is going to be + * repeated over the destination drawable + * during the composite operation, we need + * to synchronize the whole drawable to + * avoid graphical problems. + */ + + if (pSrc -> repeat == 1 || nxagentGlyphsExtents == NullBox) + { + #ifdef DEBUG + fprintf(stderr, "nxagentGlyphs: Synchronizing source [%s] at [%p] " + "with geometry [%d,%d,%d,%d].\n", + (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), + (void *) pSrc -> pDrawable, pSrc -> pDrawable -> x, pSrc -> pDrawable -> y, + pSrc -> pDrawable -> x + pSrc -> pDrawable -> width, + pSrc -> pDrawable -> y + pSrc -> pDrawable -> height); + #endif + + nxagentSynchronizeBox(pSrc -> pDrawable, NullBox, NEVER_BREAK); + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentGlyphs: Synchronizing region [%d,%d,%d,%d] of source [%s] at [%p] " + "with geometry [%d,%d,%d,%d].\n", glyphBox.x1, glyphBox.y1, glyphBox.x2, glyphBox.y2, + (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), + (void *) pSrc -> pDrawable, pSrc -> pDrawable -> x, pSrc -> pDrawable -> y, + pSrc -> pDrawable -> x + pSrc -> pDrawable -> width, + pSrc -> pDrawable -> y + pSrc -> pDrawable -> height); + #endif + + nxagentSynchronizeBox(pSrc -> pDrawable, &glyphBox, NEVER_BREAK); + } + + if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentIncreasePixmapUsageCounter((PixmapPtr) pSrc -> pDrawable); + } + } + + if (pSrc -> pDrawable != pDst -> pDrawable && + nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: Synchronizing destination [%s] at [%p].\n", + pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window", + (void *) pDst -> pDrawable); + #endif + + if (nxagentGlyphsExtents == NullBox) + { + #ifdef DEBUG + fprintf(stderr, "nxagentGlyphs: Synchronizing destination [%s] at [%p] " + "with geometry [%d,%d,%d,%d].\n", + (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), + (void *) pDst -> pDrawable, pDst -> pDrawable -> x, pDst -> pDrawable -> y, + pDst -> pDrawable -> x + pDst -> pDrawable -> width, + pDst -> pDrawable -> y + pDst -> pDrawable -> height); + #endif + + nxagentSynchronizeBox(pDst -> pDrawable, NullBox, NEVER_BREAK); + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentGlyphs: Synchronizing region [%d,%d,%d,%d] of destination [%s] at [%p] " + "with geometry [%d,%d,%d,%d].\n", glyphBox.x1, glyphBox.y1, glyphBox.x2, glyphBox.y2, + (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), + (void *) pDst -> pDrawable, pDst -> pDrawable -> x, pDst -> pDrawable -> y, + pDst -> pDrawable -> x + pDst -> pDrawable -> width, + pDst -> pDrawable -> y + pDst -> pDrawable -> height); + #endif + + nxagentSynchronizeBox(pDst -> pDrawable, &glyphBox, NEVER_BREAK); + } + + if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentIncreasePixmapUsageCounter((PixmapPtr) pDst -> pDrawable); + } + } + + nxagentSetDrawableContainGlyphs(pDst -> pDrawable, 1); + + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: Glyph flag set on drawable [%s][%p].\n", + pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window", + (void *) pDst -> pDrawable); + #endif + + #ifdef SPLIT_GLYPH_LISTS + + /* + * We split glyphs lists here and recalculate + * the offsets of each list to make them ab- + * solute and not relatives to the prior list. + * This way each time we call XRenderComposi- + * teText it has to deal only with a list of + * glyphs. This is done to further improve + * caching. + */ + + elements = elts; + + if (nlists > 1) + { + for (j = 1; j < nlists; j++) + { + x = elements -> xOff; + y = elements -> yOff; + + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: Element [%d] of [%d] has offset [%d,%d].\n", + j, nlists, elements -> xOff, elements -> yOff); + #endif + + for (i = 0; i < elements -> nchars; i++) + { + glyph = *glyphsBase++; + + x += glyph -> info.xOff; + y += glyph -> info.yOff; + + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: Glyph at index [%d] has offset [%d,%d] and " + "position [%d,%d].\n", i, elements -> nchars, glyph -> info.xOff, + glyph -> info.yOff, x, y); + #endif + } + + elements++; + + elements -> xOff += x; + elements -> yOff += y; + + #ifdef TEST + fprintf(stderr, "nxagentGlyphs: New offset for list at [%p] is [%d,%d].\n", + elements, elements -> xOff, elements -> yOff); + #endif + } + + elements = elts; + } + + switch (sizeID) + { + case 1: + { + for (j = 0; j < nlists; j++) + { + XRenderCompositeText8(nxagentDisplay, + op, + nxagentPicturePriv(pSrc)->picture, + nxagentPicturePriv(pDst)->picture, + pForm, + xSrc, + ySrc, + elements -> xOff, + elements -> yOff, + (XGlyphElt8*) elements, + 1); + + elements++; + } + + break; + } + case 2: + { + for (j = 0; j < nlists; j++) + { + XRenderCompositeText16(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + elements -> xOff, + elements -> yOff, + (XGlyphElt16*) elements, + 1); + + elements++; + } + + break; + } + case 4: + { + for (j = 0; j < nlists; j++) + { + XRenderCompositeText32(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + elements -> xOff, + elements -> yOff, + (XGlyphElt32*) elements, + 1); + + elements++; + } + + break; + } + default: + { + #ifdef WARNING + fprintf(stderr, "nxagentGlyphs: WARNING! Invalid size id [%d].\n", + sizeID); + #endif + + break; + } + } + + #else /* #ifdef SPLIT_GLYPH_LISTS */ + + elements = elts; + + switch (sizeID) + { + case 1: + { + XRenderCompositeText8(nxagentDisplay, + op, + nxagentPicturePriv(pSrc)->picture, + nxagentPicturePriv(pDst)->picture, + pForm, + xSrc, + ySrc, + elements -> xOff, + elements -> yOff, + (XGlyphElt8*) elements, + nlists); + + break; + } + case 2: + { + XRenderCompositeText16(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + elements -> xOff, + elements -> yOff, + (XGlyphElt16*) elements, + nlists); + + break; + } + case 4: + { + XRenderCompositeText32(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + elements -> xOff, + elements -> yOff, + (XGlyphElt32*) elements, + nlists); + + break; + } + default: + { + #ifdef WARNING + fprintf(stderr, "nxagentGlyphs: WARNING! Invalid size id [%d].\n", + sizeID); + #endif + + break; + } + } + + #endif /* #ifdef SPLIT_GLYPH_LISTS */ +} + +void nxagentCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, + int nRect, xRectangle *rects) +{ + RegionPtr rectRegion; + + if (pDst == NULL) + { + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentCompositeRects: Called for picture at [%p] with [%s] at [%p].\n", + (void *) pDst, (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), + (void *) pDst -> pDrawable); + #endif + + /* + * The CompositeRects() clears the destination's + * corrupted region like the PolyFillRects() does. + * As this case is harder to handle, at the moment + * we only check for two ops. + */ + + if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized && + (op == PictOpSrc || + (op == PictOpOver && color -> alpha == 0xffff))) + { + rectRegion = RECTS_TO_REGION(pDst -> pDrawable -> pScreen, nRect, rects, CT_REGION); + + if (pDst -> clientClipType != CT_NONE) + { + RegionRec tmpRegion; + + REGION_INIT(pDst -> pDrawable -> pScreen, &tmpRegion, NullBox, 1); + + REGION_COPY(pDst -> pDrawable -> pScreen, &tmpRegion, (RegionPtr) pDst -> clientClip); + + if (pDst -> clipOrigin.x != 0 || pDst -> clipOrigin.y != 0) + { + REGION_TRANSLATE(pDst -> pDrawable -> pScreen, &tmpRegion, pDst -> clipOrigin.x, pDst -> clipOrigin.y); + } + + REGION_INTERSECT(pDst -> pDrawable -> pScreen, rectRegion, rectRegion, &tmpRegion); + + REGION_UNINIT(pDst -> pDrawable -> pScreen, &tmpRegion); + } + + #ifdef TEST + fprintf(stderr, "nxagentCompositeRects: Going to clean the drawable with extents [%d,%d,%d,%d].\n", + rectRegion -> extents.x1, rectRegion -> extents.y1, rectRegion -> extents.x2, rectRegion -> extents.y2); + #endif + + nxagentUnmarkCorruptedRegion(pDst -> pDrawable, rectRegion); + + REGION_DESTROY(pDrawable -> pScreen, rectRegion); + } + + XRenderFillRectangles(nxagentDisplay, + op, + (Picture)nxagentPicturePriv(pDst) -> picture, + (XRenderColor *) color, + (XRectangle *) rects, + nRect); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps) +{ + XRenderPictFormat *pForm; + + XTrapezoid *current = (XTrapezoid *) traps; + + RegionPtr pDstRegion; + + int remaining = ntrap; + + #ifdef TEST + fprintf(stderr, "nxagentTrapezoids: Source [%p] destination [%p] coordinates " + "[%d,%d] elements [%d].\n", (void *) pSrc, (void *) pDst, + xSrc, ySrc, ntrap); + #endif + + if (pSrc == NULL || pDst == NULL) + { + return; + } + + pForm = NULL; + + if (maskFormat != NULL) + { + pForm = nxagentMatchingFormats(maskFormat); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + + if (pForm == NULL) + { + return; + } + } +/* +FIXME: Is this useful or just a waste of bandwidth? + + Apparently useless with QT. +*/ + #ifndef SKIP_LOUSY_RENDER_OPERATIONS + + #ifdef TEST + + fprintf(stderr, "nxagentTrapezoids: Source is a [%s] of geometry [%d,%d].\n", + (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), + pSrc -> pDrawable -> width, pSrc -> pDrawable -> height); + + if (pSrc ->pDrawable != pDst -> pDrawable) + { + fprintf(stderr, "nxagentTrapezoids: Destination is a [%s] of geometry [%d,%d].\n", + (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), + pDst -> pDrawable -> width, pDst -> pDrawable -> height); + } + + #endif + + /* + * If the destination drawable is not synchronized + * but the trapezoids extents are included in the + * dirty region, we can defer the operation. + */ + + if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized && + RECT_IN_REGION(pDst -> pDrawable -> pScreen, nxagentCorruptedRegion(pDst -> pDrawable), + nxagentTrapezoidExtents) == rgnIN) + { + #ifdef TEST + fprintf(stderr, "nxagentTrapezoids: WARNING! Prevented operation on region [%d,%d,%d,%d] already dirty " + "for drawable [%s][%p].\n", nxagentTrapezoidExtents -> x1, nxagentTrapezoidExtents -> y1, + nxagentTrapezoidExtents -> x2, nxagentTrapezoidExtents -> y2, + pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window", + (void *) pDst -> pDrawable); + #endif + + if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapContainTrapezoids((PixmapPtr) pDst -> pDrawable) = 1; + } + + return; + } + + /* + * If the destination doesn't contain any glyphs, + * we can defer the trapezoids drawing by marking + * the destination as dirty. + */ + + if (NXAGENT_SHOULD_DEFER_TRAPEZOIDS(pDst -> pDrawable)) + { + pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, + nxagentTrapezoidExtents -> x1, + nxagentTrapezoidExtents -> y1, + nxagentTrapezoidExtents -> x2 - nxagentTrapezoidExtents -> x1, + nxagentTrapezoidExtents -> y2 - nxagentTrapezoidExtents -> y1); + + #ifdef TEST + fprintf(stderr, "nxagentTrapezoids: WARNING! Prevented operation on region [%d,%d,%d,%d] " + "for drawable [%s][%p].\n", pDstRegion -> extents.x1, pDstRegion -> extents.y1, + pDstRegion -> extents.x2, pDstRegion -> extents.y2, + pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window", + (void *) pDst -> pDrawable); + #endif + + nxagentMarkCorruptedRegion(pDst -> pDrawable, pDstRegion); + + nxagentFreeRegion(pDst -> pDrawable, pDstRegion); + + if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapContainTrapezoids((PixmapPtr) pDst -> pDrawable) = 1; + } + + return; + } + + if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTrapezoids: Going to synchronize the source drawable at [%p].\n", + (void *) pSrc -> pDrawable); + #endif + + nxagentSynchronizeBox(pSrc -> pDrawable, NullBox, NEVER_BREAK); + } + + if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTrapezoids: Going to synchronize the destination drawable at [%p].\n", + (void *) pDst -> pDrawable); + #endif + + nxagentSynchronizeBox(pDst -> pDrawable, nxagentTrapezoidExtents, NEVER_BREAK); + } + + while (remaining > 0) + { + XRenderCompositeTrapezoids(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + (XTrapezoid *) current, + (remaining > TRAPEZOIDS_PER_REQUEST ? + TRAPEZOIDS_PER_REQUEST : remaining)); + + remaining -= TRAPEZOIDS_PER_REQUEST; + current += TRAPEZOIDS_PER_REQUEST; + } + + #endif + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentRasterizeTrapezoid(PicturePtr pMask, xTrapezoid *trap, + int x_off, int y_off) +{ + #ifdef DEBUG + fprintf(stderr, "nxagentRasterizeTrapezoids: Nothing to do.\n"); + #endif +} + +void nxagentTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle *tris) +{ + XRenderPictFormat *pForm; + + #ifdef DEBUG + fprintf(stderr, "nxagentTriangles: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n", + (void *) pSrc, (void *) pDst, xSrc, ySrc, ntri); + #endif + + if (pSrc == NULL || pDst == NULL) + { + return; + } + + pForm = NULL; + + if (maskFormat != NULL) + { + pForm = nxagentMatchingFormats(maskFormat); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + + if (pForm == NULL) + { + return; + } + } + + /* + * If the X_RenderCompositeTriangles requests + * increment the traffic, we can defer the + * operation like nxagentTrapezoids() does. + */ + + if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTriangles: Going to synchronize the source drawable at [%p].\n", + (void *) pSrc -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + + if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTriangles: Going to synchronize the destination drawable at [%p].\n", + (void *) pDst -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + + XRenderCompositeTriangles(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + (XTriangle*)tris, + ntri); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed *points) +{ + XRenderPictFormat *pForm; + + #ifdef DEBUG + fprintf(stderr, "nxagentTriStrip: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n", + (void *) pSrc, (void *) pDst, xSrc, ySrc, npoint); + #endif + + if (pSrc == NULL || pDst == NULL) + { + return; + } + + pForm = NULL; + + if (maskFormat != NULL) + { + pForm = nxagentMatchingFormats(maskFormat); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + + if (pForm == NULL) + { + return; + } + } + + /* + * If the X_RenderCompositeTriStrip requests + * increment the traffic, we can defer the + * operation like nxagentTrapezoids() does. + */ + + if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTriStrip: Going to synchronize the source drawable at [%p].\n", + (void *) pSrc -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + + if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTriStrip: Going to synchronize the destination drawable at [%p].\n", + (void *) pDst -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + + XRenderCompositeTriStrip(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + (XPointFixed*)points, + npoint); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int npoint, xPointFixed *points) +{ + XRenderPictFormat *pForm; + + #ifdef DEBUG + fprintf(stderr, "nxagentTriFan: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n", + (void *) pSrc, (void *) pDst, xSrc, ySrc, npoint); + #endif + + if (pSrc == NULL || pDst == NULL) + { + return; + } + + pForm = NULL; + + if (maskFormat != NULL) + { + pForm = nxagentMatchingFormats(maskFormat); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + + if (pForm == NULL) + { + return; + } + } + + /* + * If the X_RenderCompositeTriFan requests + * increment the traffic, we can defer the + * operation like nxagentTrapezoids() does. + */ + + if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTriFan: Going to synchronize the source drawable at [%p].\n", + (void *) pSrc -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + + if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentTriFan: Going to synchronize the destination drawable at [%p].\n", + (void *) pDst -> pDrawable); + #endif + + nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL); + } + + XRenderCompositeTriFan(nxagentDisplay, + op, + nxagentPicturePriv(pSrc) -> picture, + nxagentPicturePriv(pDst) -> picture, + pForm, + xSrc, + ySrc, + (XPointFixed*)points, + npoint); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +#ifndef NXAGENT_UPGRADE + +/* +FIXME: In the 3.0.0 port these functions have been moved + to Picture.c. We can remove them when the port is + is complete. +*/ +int AllocatePicturePrivateIndex() +{ + return picturePrivateCount++; +} + +Bool AllocatePicturePrivate(register ScreenPtr pScreen, int index2, unsigned amount) +{ + unsigned oldamount; + + PictureScreenPtr ps = GetPictureScreen(pScreen); + + /* + * Round up the size for proper alignment. + */ + + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= ps -> PicturePrivateLen) + { + unsigned *nsizes = (unsigned *) xrealloc(ps -> PicturePrivateSizes, + (index2 + 1) * sizeof(unsigned)); + if (nsizes == 0) + { + return 0; + } + + while (ps -> PicturePrivateLen <= index2) + { + nsizes[ps -> PicturePrivateLen++] = 0; + + ps -> totalPictureSize += sizeof(DevUnion); + } + + ps -> PicturePrivateSizes = nsizes; + } + + oldamount = ps -> PicturePrivateSizes[index2]; + + if (amount > oldamount) + { + ps -> PicturePrivateSizes[index2] = amount; + + ps -> totalPictureSize += (amount - oldamount); + } + + return 1; +} +#endif + +void nxagentQueryFormats() +{ + XRenderInfo *xri; + XExtDisplayInfo *info = NULL; + XRenderPictFormat *pformat=NULL; + + int i; + + #ifdef DEBUG + fprintf(stderr, "nxagentQueryFormats.\n"); + #endif + + if (XRenderQueryFormats(nxagentDisplay)) + { + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif + + info = (XExtDisplayInfo *) XRenderFindDisplay(nxagentDisplay); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif + + xri = (XRenderInfo *) info -> data; + + pformat = xri -> format; + + for (i = 0; i < xri -> nformat; i++) + { + nxagentArrayFormats[i] = *pformat; + + #ifdef DEBUG + fprintf(stderr, "nxagentQueryFormats: Added format type [%d] depth [%d] rgb [%d,%d,%d] " + "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d].\n", + nxagentArrayFormats[i].type, nxagentArrayFormats[i].depth, nxagentArrayFormats[i].direct.red, + nxagentArrayFormats[i].direct.green, nxagentArrayFormats[i].direct.blue, + nxagentArrayFormats[i].direct.redMask, nxagentArrayFormats[i].direct.greenMask, + nxagentArrayFormats[i].direct.blueMask, nxagentArrayFormats[i].direct.alpha, + nxagentArrayFormats[i].direct.alphaMask); + #endif + + pformat++; + } + + #ifdef DEBUG + + if (nxagentNumFormats == 0) + { + fprintf(stderr, "nxagentQueryFormats: Number of formats is [%d].\n", + i); + } + else + { + fprintf(stderr, "nxagentQueryFormats: Old number of formats is [%d]. New number of formats is [%d].\n", + nxagentNumFormats, i); + } + + #endif + + nxagentNumFormats = i; + } +} + +void nxagentCreateGlyphSet(GlyphSetPtr pGly) +{ + XRenderPictFormat *pForm; + + #ifdef DEBUG + fprintf(stderr, "nxagentCreateGlyphSet: Glyphset at [%p].\n", (void *) pGly); + #endif + + pForm = NULL; + + if (pGly -> format != NULL) + { + pForm = nxagentMatchingFormats(pGly -> format); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + + if (pForm == NULL) + { + return; + } + } + + pGly -> remoteID = XRenderCreateGlyphSet(nxagentDisplay, pForm); + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet) +{ + if (glyphSet -> remoteID == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentReferenceGlyphSet: Operation deferred because glyphset at [%p] is corrupted.\n", + (void *) glyphSet); + #endif + + return; + } + + XRenderReferenceGlyphSet (nxagentDisplay, glyphSet -> remoteID); +} + +void nxagentFreeGlyphSet(GlyphSetPtr glyphSet) +{ + if (glyphSet -> remoteID == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentFreeGlyphs: Operation ignored because glyphset at [%p] is corrupted.\n", + (void *) glyphSet); + #endif + + return; + } + + XRenderFreeGlyphSet(nxagentDisplay, glyphSet -> remoteID); +} + +void nxagentAddGlyphs(GlyphSetPtr glyphSet, Glyph *gids, xGlyphInfo *gi, + int nglyphs, CARD8 *images, int sizeImages) +{ + GlyphRefPtr gr; + Glyph *tempGids; + + int i; + + CARD8 *normalizedImages; + + #ifdef DEBUG + fprintf(stderr, "nxagentAddGlyphs: Glyphset at [%p]. Number of glyphs [%d].\n", + (void *) glyphSet, nglyphs); + #endif + + if (glyphSet -> remoteID == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentAddGlyphs: Going to reconnect the glyhpset at [%p] before adding glyphs.\n", + (void *) glyphSet); + #endif + + nxagentReconnectGlyphSet(glyphSet, (XID) 0, (void*) NULL); + } + + /* + * By adding a glyph to a glyphset on + * remote X server we mark its reference + * as synchronized. + */ + + tempGids = gids; + + for (i = 0; i < nglyphs; i++) + { + if ((gr = FindGlyphRef(&glyphSet -> hash, *tempGids, 0, 0)) && + gr -> glyph != DeletedGlyph) + { + #ifdef DEBUG + fprintf(stderr, "nxagentAddGlyphs: Added Glyph [%p][%ld] to glyphset [%p].\n", + (void *) gr -> glyph, *tempGids, (void *) glyphSet); + #endif + + gr -> corruptedGlyph = 0; + } + + tempGids++; + } + + normalizedImages = NULL; + + if (glyphDepths[glyphSet -> fdepth] == 1 && + nxagentServerOrder() != BitmapBitOrder(nxagentDisplay)) + { + normalizedImages = xalloc(sizeImages); + + if (normalizedImages != NULL) + { + memcpy(normalizedImages, images, sizeImages); + + BitOrderInvert ((unsigned char *) normalizedImages, sizeImages); + } + else + { + #ifdef PANIC + fprintf(stderr, "nxagentAddGlyphs: PANIC! Allocation of normalized glyph images failed.\n"); + #endif + } + } + + if (normalizedImages == NULL) + { + normalizedImages = images; + } + + XRenderCleanGlyphs(gi, nglyphs, normalizedImages, glyphDepths[glyphSet -> fdepth], nxagentDisplay); + + XRenderAddGlyphs(nxagentDisplay, + glyphSet -> remoteID, + gids, + (XGlyphInfo*)(gi), + nglyphs, + (char*) normalizedImages, + sizeImages); + + if (normalizedImages != images) + { + xfree(normalizedImages); + } + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif +} + +void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph) +{ + GlyphRefPtr gr; + CARD32 *tempGids; + Glyph gid; + + int i; + + if (glyphSet -> remoteID == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentFreeGlyphs: Operation ignored because glyphset at [%p] is corrupted.\n", + (void *) glyphSet); + #endif + + return; + } + + /* + * We loop across the list of glyphs id + * to establish if they have been added + * to glyphset on remote X server, so + * they can be freed. + */ + + tempGids = gids; + + for (i = 0; i < nglyph; i++) + { + gid = (Glyph)*tempGids; + + if ((gr = FindGlyphRef(&glyphSet -> hash, *tempGids, 0, 0)) && + gr -> glyph != DeletedGlyph && + gr -> corruptedGlyph == 0) + { + XRenderFreeGlyphs(nxagentDisplay, glyphSet -> remoteID, &gid, 1); + } + + tempGids++; + } +} + +void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform) +{ + #ifdef TEST + fprintf(stderr, "nxagentSetPictureTransform: Going to set transform [%p] to picture at [%p].\n", + (void *) transform, (void *) pPicture); + #endif + +/* +FIXME: Is this useful or just a waste of bandwidth? + + Apparently useless with QT. +*/ + #ifndef SKIP_LOUSY_RENDER_OPERATIONS + + XRenderSetPictureTransform(nxagentDisplay, + nxagentPicturePriv(pPicture) -> picture, + (XTransform *) transform); + #endif +} + +void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size, + pointer params, int nparams) +{ + char *szFilter = Xmalloc(name_size + 1); + + if (szFilter == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentSetPictureFilter: error allocating memory for filter name.\n"); + #endif + + return; + } + + strncpy(szFilter, filter, name_size); + + szFilter[name_size] = 0; + + #ifdef TEST + fprintf(stderr, "nxagentSetPictureFilter: Going to set filter [%s] to picture at [%p].\n", + szFilter, (void *) pPicture); + #endif +/* +FIXME: Is this useful or just a waste of bandwidth? + + Apparently useless with QT. +*/ + #ifndef SKIP_LOUSY_RENDER_OPERATIONS + + XRenderSetPictureFilter(nxagentDisplay, + nxagentPicturePriv(pPicture) -> picture, + szFilter, + (XFixed *) params, + nparams); + #endif + + Xfree(szFilter); +} + + +Bool nxagentPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + #ifdef RENDER + + #ifdef DEBUG + fprintf(stderr, "nxagentPictureInit: Screen [%p].\n", (void *) pScreen); + #endif + + nxagentQueryFormats(); + + if (fbPictureInit(pScreen, formats, nformats) == 0) + { + return FALSE; + } + + nxagentPicturePrivateIndex = AllocatePicturePrivateIndex(); + + AllocatePicturePrivate(pScreen, nxagentPicturePrivateIndex, sizeof(nxagentPrivPictureRec)); + + #endif + + return TRUE; +} + +#ifdef DEBUG + +static void nxagentPrintFormat(XRenderPictFormat *pFormat) +{ + if (pFormat == NULL) + { + fprintf(stderr, "nxagentPrintFormat: WARNING! null pointer passed to function.\n"); + + return; + } + + fprintf(stderr, "nxagentPrintFormat: Dumping information for format at [%p]:\n\ + type=%d\n\ + depth=%d\n\ + red=%d\n\ + redMask=%d\n\ + green=%d\n\ + greenMask=%d\n\ + blue=%d\n\ + blueMask=%d\n\ + alpha=%d\n\ + alphaMask=%d\n", + (void *) pFormat, + pFormat -> type, + pFormat -> depth, + pFormat -> direct.red, + pFormat -> direct.redMask, + pFormat -> direct.green, + pFormat -> direct.greenMask, + pFormat -> direct.blue, + pFormat -> direct.blueMask, + pFormat -> direct.alpha, + pFormat -> direct.alphaMask); +} + +#endif + +Bool nxagentFillGlyphSet(GlyphSetPtr pGly) +{ + GlyphPtr glyph; + + int i; + + #ifdef DEBUG + fprintf(stderr, "nxagentFillGlyphSet: GlyphSet at [%p] Refcount [%ld] Glyphs [%ld] " + "Format [%p] FDepth [%d] RemoteID [%ld].\n", (void *) pGly, pGly -> refcnt, + pGly -> hash.hashSet -> size, (void *) pGly -> format, pGly -> fdepth, pGly -> remoteID); + #endif + + /* + * The glyphs are synchronized when they + * are used in a composite text. During + * the reconnection we have only to mark + * corrupted the glyphs for each glyphset. + */ + + for (i = 0; i < pGly -> hash.hashSet -> size; i++) + { + glyph = pGly -> hash.table[i].glyph; + + if (glyph && (glyph != DeletedGlyph)) + { + pGly -> hash.table[i].corruptedGlyph = 1; + } + } + + return TRUE; +} + +void nxagentReconnectGlyphSet(void* p0, XID x1, void *p2) +{ + GlyphSetPtr pGly = (GlyphSetPtr) p0; + + XRenderPictFormat *pForm = NULL; + + int i; + + if (nxagentReconnectTrap == 0) + { + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectGlyphSet: GlyphSet at [%p].\n", (void *) pGly); + #endif + + if (pGly -> format) + { + pForm = nxagentMatchingFormats(pGly -> format); + } + + pGly -> remoteID = XRenderCreateGlyphSet(nxagentDisplay, pForm); + + /* + * If we have deferred the operation, we + * have to check the number of references + * to the glyphset to update the X server. + */ + + if ((i = pGly -> refcnt) > 1) + { + while (i-- > 1) + { + nxagentReferenceGlyphSet(pGly); + } + } + + #ifdef DEBUG + + XSync(nxagentDisplay, 0); + + #endif + + nxagentFillGlyphSet(pGly); + } + else + { + pGly -> remoteID = 0; + } +} + +Bool nxagentReconnectAllGlyphSet(void *p) +{ + Bool success = TRUE; + int i; + + nxagentQueryFormats(); + + #ifdef DEBUG + fprintf(stderr, "nxagentReconnectAllGlyphSet\n"); + #endif + + for (i = 0; (i < MAXCLIENTS) && (success); i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], GlyphSetType, nxagentReconnectGlyphSet, &success); + } + } + + return success; +} + +void nxagentReconnectPicture(pointer p0, XID x1, void *p2) +{ + PicturePtr pPicture = (PicturePtr) p0; + Bool *pBool = (Bool *) p2; + unsigned long mask = 0; + + XRenderPictureAttributes attributes; + XRenderPictFormat *pForm; + + #ifdef TEST + fprintf(stderr, "nxagentReconnectPicture: Called with bool [%d] and picture at [%p].\n", + *pBool, (void *) pPicture); + + fprintf(stderr, "nxagentReconnectPicture: Virtual picture is [%ld].\n", + nxagentPicture(pPicture)); + #endif + + /* + * Check if a previous operation has failed + * and that the involved objects are valid. + */ + + if (*pBool == 0 || pPicture == NULL || + nxagentPicture(pPicture) != 0) + { + return; + } + + if (pPicture -> repeat) + { + mask |= CPRepeat; + + attributes.repeat = (Bool) pPicture -> repeat; + } + + if (pPicture -> alphaMap) + { + if (!nxagentPicture(pPicture -> alphaMap)) + { + nxagentReconnectPicture(pPicture -> alphaMap, 0, pBool); + + if (!*pBool || !nxagentPicture(pPicture -> alphaMap)) + { + return; + } + } + + attributes.alpha_map = nxagentPicture(pPicture -> alphaMap); + attributes.alpha_x_origin = pPicture -> alphaOrigin.x; + attributes.alpha_y_origin = pPicture -> alphaOrigin.y; + + mask |= (CPAlphaMap | CPAlphaXOrigin | CPAlphaYOrigin); + } + + if (pPicture -> graphicsExposures) + { + attributes.graphics_exposures = pPicture -> graphicsExposures; + + mask |= CPGraphicsExposure; + } + + attributes.subwindow_mode = pPicture -> subWindowMode; + + mask |= CPSubwindowMode; + + attributes.poly_edge = pPicture -> polyEdge; + + mask |= CPPolyEdge; + + attributes.poly_mode = pPicture -> polyMode; + + mask |= CPPolyMode; + + attributes.dither = pPicture -> dither; + + mask |= CPDither; + + attributes.component_alpha = pPicture -> componentAlpha; + + mask |= CPComponentAlpha; + + pForm = NULL; + + if (pPicture -> pFormat) + { + pForm = nxagentMatchingFormats(pPicture -> pFormat); + + #ifdef DEBUG + + nxagentPrintFormat(pForm); + + #endif + } + + if (!pForm) + { + *pBool = False; + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentReconnectPicture: Creating picture at [%p] with drawable [%ld] at [%p].\n", + (void *) pPicture, nxagentDrawable(pPicture -> pDrawable), (void *) pPicture -> pDrawable); + + fprintf(stderr, "nxagentReconnectPicture: Format is at [%p] mask is [%ld] attributes are at [%p].\n", + (void *) pForm, mask, (void *) &attributes); + #endif + + nxagentPicture(pPicture) = XRenderCreatePicture(nxagentDisplay, + nxagentDrawable(pPicture -> pDrawable), + pForm, + mask, + &attributes); + + #ifdef TEST + + XSync(nxagentDisplay, 0); + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentReconnectPicture: Reconnected picture at [%p] with value [%ld].\n", + (void *) pPicture, nxagentPicture(pPicture)); + #endif + + if (nxagentAlphaEnabled == 1 && pPicture -> pDrawable -> depth == 32 && + pPicture -> pFormat -> direct.alpha != 0) + { + if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapPriv((PixmapPtr) pPicture -> pDrawable) -> pPicture = pPicture; + } + else if (pPicture -> pDrawable -> type == DRAWABLE_WINDOW) + { + nxagentWindowPriv((WindowPtr) pPicture -> pDrawable) -> pPicture = pPicture; + } + } +} + +Bool nxagentReconnectAllPicture(void *p) +{ + int i; + Bool r; + + #ifdef TEST + fprintf(stderr, "nxagentReconnectAllPicture: Going to recreate all pictures.\n"); + #endif + + for (i = 0, r = 1; i < MAXCLIENTS; i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], PictureType, nxagentReconnectPicture, &r); + + #ifdef WARNING + + if (r == False) + { + fprintf(stderr, "nxagentReconnectAllPicture: WARNING! Failed to recreate " + "picture for client [%d].\n", i); + } + + #endif + } + } + + return True; +} + +void nxagentDisconnectPicture(pointer p0, XID x1, void* p2) +{ + PicturePtr pPicture = (PicturePtr) p0; + Bool *pBool = (Bool *) p2; + + #ifdef TEST + fprintf(stderr, "nxagentDisconnectPicture: Called with bool [%d] and picture at [%p].\n", + *pBool, (void *) pPicture); + + fprintf(stderr, "nxagentDisconnectPicture: Virtual picture is [%ld].\n", + nxagentPicture(pPicture)); + #endif + + if (!*pBool || !pPicture) + { + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentDisconnectPicture: %p - XID %lx\n", + (void *) pPicture, nxagentPicture(pPicture)); + #endif + + nxagentPicture(pPicture) = None; +} + +Bool nxagentDisconnectAllPicture() +{ + int i; + Bool r; + + #ifdef DEBUG + fprintf(stderr, "nxagentDisconnectAllPicture.\n"); + #endif + + for (i = 0, r = 1; i < MAXCLIENTS; i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], PictureType, nxagentDisconnectPicture, &r); + + #ifdef WARNING + + if (r == False) + { + fprintf(stderr, "nxagentDisconnectAllPicture: WARNING! Failed to disconnect " + "picture for client [%d].\n", i); + } + + #endif + } + } + + return True; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Render.h b/nx-X11/programs/Xserver/hw/nxagent/Render.h new file mode 100644 index 000000000..240dc3901 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Render.h @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Render_H__ +#define __Render_H__ + +#include "screenint.h" +#include "picture.h" +#include "renderproto.h" + +#include "NXglyphstr.h" + +#include "Agent.h" + +extern int nxagentRenderEnable; +extern int nxagentRenderVersionMajor; +extern int nxagentRenderVersionMinor; + +extern int nxagentPicturePrivateIndex; + +extern BoxPtr nxagentGlyphsExtents; +extern BoxPtr nxagentTrapezoidExtents; + +/* + * Structure imported from Xrender.h. We don't + * include Xrender.h at this point because of + * clashes of definition. + */ + +/* + * Xlib Pixmap and Atom types are 8 bytes long + * on 64-bit archs, whilst they are 4 bytes long + * on 32-bit ones. At this point, Pixmap and Atom + * are not Xlib types but Xserver ones: here they + * are always 4 bytes long. So that we use XlibID + * symbols defined below to fill the structure with + * fields having the right size. + */ + +typedef struct { + int repeat; + Picture alpha_map; + int alpha_x_origin; + int alpha_y_origin; + int clip_x_origin; + int clip_y_origin; + XlibPixmap clip_mask; + Bool graphics_exposures; + int subwindow_mode; + int poly_edge; + int poly_mode; + XlibAtom dither; + Bool component_alpha; +} XRenderPictureAttributes_; + +typedef struct +{ + Picture picture; + + XRenderPictureAttributes_ lastServerValues; + +} nxagentPrivPictureRec; + +typedef nxagentPrivPictureRec *nxagentPrivPicturePtr; + +#define nxagentPicturePriv(pPicture) \ + ((nxagentPrivPicturePtr) ((pPicture) -> devPrivates[nxagentPicturePrivateIndex].ptr)) + +#define nxagentPicture(pPicture) (nxagentPicturePriv(pPicture) -> picture) + +#define nxagentSetPictureRemoteValue(pPicture, pvalue, value) \ +do \ +{ \ + nxagentPicturePriv(pPicture) -> lastServerValues.pvalue = value; \ +} \ +while (0) + +#define nxagentCheckPictureRemoteValue(pPicture, pvalue, value) \ + (nxagentPicturePriv(pPicture) -> lastServerValues.pvalue == value) + +void nxagentRenderExtensionInit(void); +Bool nxagentPictureInit(ScreenPtr, PictFormatPtr, int); + +int nxagentRenderRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); + +void nxagentAddGlyphs(GlyphSetPtr glyphSet, Glyph *gids, xGlyphInfo *gi, + int nglyphs, CARD8 *images, int sizeImages); + +void nxagentReconnectPicture(pointer p0, XID x1, void *p2); +void nxagentDisconnectPicture(pointer p0, XID x1, void* p2); + +void nxagentReconnectGlyphSet(void* p0, XID x1, void *p2); + +#endif /* __Render_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Rootless.c b/nx-X11/programs/Xserver/hw/nxagent/Rootless.c new file mode 100644 index 000000000..cd69af665 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Rootless.c @@ -0,0 +1,1112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "X.h" + +#include "../../include/window.h" +#include "windowstr.h" +#include "colormapst.h" +#include "propertyst.h" + +#include "Agent.h" +#include "Display.h" +#include "Drawable.h" +#include "Windows.h" +#include "Pixmaps.h" +#include "Atoms.h" +#include "Trap.h" + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Assigned at the time the root window is + * initialized. + */ + +WindowPtr nxagentRootlessWindow = NULL; + +#define TOP_LEVEL_TABLE_UNIT 100 + +typedef struct { + Window xid; + WindowPtr pWin; +} TopLevelParentRec; + +typedef struct { + TopLevelParentRec *elt; + int next; + int size; +} TopLevelParentMap; + +static TopLevelParentMap topLevelParentMap = { NULL, 0, 0 }; + +static void nxagentRemovePropertyFromList(void); + +/* + * This is currently unused. + */ + +#ifdef TEST + +static void nxagentPrintRootlessTopLevelWindowMap(void); + +void nxagentPrintRootlessTopLevelWindowMap() +{ + int i; + + fprintf(stderr, "nxagentPrintRootlessTopLevelWindowMap: Map size is [%d] num of entry [%d].\n", + topLevelParentMap.size, topLevelParentMap.next); + + for (i = 0; i < topLevelParentMap.next; i++) + { + fprintf(stderr, "nxagentPrintRootlessTopLevelWindowMap: [%d] pWin at [%p] XID at [%ld].\n", + i, (void *) topLevelParentMap.elt[i].pWin, (long int) topLevelParentMap.elt[i].xid); + } +} + +#endif + +void nxagentRootlessAddTopLevelWindow(WindowPtr pWin, Window w) +{ + int i; + + for (i = 0; i < topLevelParentMap.next; i++) + { + if (topLevelParentMap.elt[i].pWin == pWin) + { + #ifdef TEST + fprintf(stderr, "nxagentRootlessAddTopLevelWindow: WARNING! " + "Trying to add duplicated entry window at [%p] xid [%ld].\n", + (void *) pWin, w); + #endif + + topLevelParentMap.elt[i].xid = w; + + return; + } + } + + if (topLevelParentMap.next == topLevelParentMap.size) + { + TopLevelParentRec *ptr = topLevelParentMap.elt; + size_t size = (topLevelParentMap.size += TOP_LEVEL_TABLE_UNIT); + + ptr = realloc(ptr, size * sizeof(TopLevelParentRec)); + + if (ptr == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentRootlessAddTopLevelWindow: Warning failed to allocate memory.\n"); + #endif + + return; + } + + topLevelParentMap.elt = ptr; + topLevelParentMap.size = size; + } + + topLevelParentMap.elt[topLevelParentMap.next].xid = w; + topLevelParentMap.elt[topLevelParentMap.next].pWin = pWin; + topLevelParentMap.next++; +} + +WindowPtr nxagentRootlessTopLevelWindow(Window w) +{ + int i; + + for (i = 0; i < topLevelParentMap.next; i++) + { + if (w == topLevelParentMap.elt[i].xid) + { + return topLevelParentMap.elt[i].pWin; + } + } + + return NULL; +} + +void nxagentRootlessDelTopLevelWindow(WindowPtr pWin) +{ + int i; + + for (i = 0; i < topLevelParentMap.next; i++) + { + if (pWin == topLevelParentMap.elt[i].pWin) + { + topLevelParentMap.elt[i] = topLevelParentMap.elt[topLevelParentMap.next - 1]; + topLevelParentMap.next--; + + return; + } + } +} + +Window nxagentRootlessWMTopLevelWindow(WindowPtr pWin); + +void nxagentConfigureRootlessWindow(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib, int stack_mode, Mask mask) +{ + XWindowChanges changes; + Window sibw = 0; + + changes.x = x; + changes.y = y; + changes.width = w; + changes.height = h; + changes.border_width = bw; + changes.stack_mode = stack_mode; + + if (pSib) + { + sibw = nxagentWindow(pSib); + } + + if (sibw) + { + changes.sibling = sibw; + } + + XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), mask, &changes); +} + +void nxagentCirculateRootlessWindows(int direction) +{ + XCirculateSubwindows(nxagentDisplay, DefaultRootWindow(nxagentDisplay), direction); +} + +#ifdef DEBUG + +Bool nxagentRootlessTreesMatch() +{ + Window root_return; + Window parent_return; + Window *children_return; + unsigned int nChildrenReturn; + WindowPtr pW; + WindowPtr pTestWin = WindowTable[0] -> firstChild; + Bool treesMatch = True; + Status result; + + result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + &root_return, &parent_return, &children_return, &nChildrenReturn); + + if (!result) + { + #ifdef WARNING + fprintf(stderr, "nxagentRootlessTreesMatch: WARNING! Failed QueryTree request.\n"); + #endif + + return False; + } + + while (nChildrenReturn > 0) + { + pW = nxagentWindowPtr(children_return[--nChildrenReturn]); + + if (!pW) + { + pW = nxagentRootlessTopLevelWindow(children_return[nChildrenReturn]); + } + + if (pW && pW != WindowTable[0]) + { + if (treesMatch && pTestWin && pTestWin == pW) + { + pTestWin = pTestWin -> nextSib; + } + else + { + treesMatch = False; + } + } + } + + if (children_return) + { + XFree(children_return); + } + + return treesMatch; +} + +#endif + +#ifndef _XSERVER64 +void nxagentRootlessRestack(Window children[], unsigned int nchildren) +#else +void nxagentRootlessRestack(unsigned long children[], unsigned int nchildren) +#endif +{ + WindowPtr *toplevel; + unsigned int ntoplevel; + int i; + WindowPtr pWin; + ClientPtr pClient; + XID values[2]; + Mask mask; + + toplevel = xalloc(sizeof(WindowPtr) * nchildren); + ntoplevel = 0; + + for(i = 0; i < nchildren; i++) + { + pWin = nxagentWindowPtr(children[i]); + + if (!pWin) + { + pWin = nxagentRootlessTopLevelWindow(children[i]); + } + + if (pWin && pWin != WindowTable[0]) + { + toplevel[ntoplevel++] = pWin; + } + } + + if (!ntoplevel) + { + return; + } + + #ifdef DEBUG + + fprintf(stderr, "nxagentRootlessRestack: External top level windows before restack:"); + + for (i = 0; i < ntoplevel; i++) + { + fprintf(stderr, "[%p]\n", toplevel[i]); + } + + fprintf(stderr, "nxagentRootlessRestack: Internal top level windows before restack:"); + + for (pWin = WindowTable[0] -> firstChild; pWin != NULL; pWin = pWin -> nextSib) + { + fprintf(stderr, "[%p]\n", pWin); + } + + #endif + + pWin = WindowTable[0] -> firstChild; + + values[1] = (XID) Above; + + while(ntoplevel-- > 0 && pWin != NULL) + { + if (toplevel[ntoplevel] != pWin) + { + mask = CWSibling | CWStackMode; + values[0] = pWin -> drawable.id; + pClient = wClient(toplevel[ntoplevel]); + nxagentScreenTrap = 1; + ConfigureWindow(toplevel[ntoplevel], mask, (XID *) values, pClient); + nxagentScreenTrap = 0; + + #ifdef TEST + fprintf(stderr, "nxagentRootlessRestack: Restacked window [%p].\n", (void*) toplevel[ntoplevel]); + #endif + } + + pWin = toplevel[ntoplevel] -> nextSib; + } + + #ifdef DEBUG + + fprintf(stderr, "nxagentRootlessRestack: External top level windows after restack:"); + + ntoplevel = i; + + for (i = 0; i < ntoplevel; i++) + { + fprintf(stderr, "[%p]\n", toplevel[i]); + } + + fprintf(stderr, "nxagentRootlessRestack: Internal top level windows after restack:"); + + for (pWin = WindowTable[0] -> firstChild; pWin != NULL; pWin = pWin -> nextSib) + { + fprintf(stderr, "[%p]\n", pWin); + } + + #endif + + xfree(toplevel); + + return; +} + +/* + * Determine if window is a top-level window. + */ + +Window nxagentRootlessWindowParent(WindowPtr pWin) +{ + #ifdef TEST + fprintf(stderr, "nxagentRootlessWindowParent: Called for window at [%p][%ld] with parent [%p][%ld].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin->parent, + (pWin->parent ? nxagentWindowPriv(pWin->parent)->window : 0)); + #endif + + if (pWin -> parent == NULL) + { + return DefaultRootWindow(nxagentDisplay); + } + else if (pWin -> parent == nxagentRootlessWindow) + { + return DefaultRootWindow(nxagentDisplay); + } + else + { + return nxagentWindow(pWin -> parent); + } +} + +int nxagentExportAllProperty(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp; + int total = 0; + + for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) + { + total += nxagentExportProperty(pWin, + pProp->propertyName, + pProp->type, + pProp->format, + PropModeReplace, + pProp->size, + pProp->data); + } + + return total; +} + +int nxagentExportProperty(pWin, property, type, format, mode, nUnits, value) + WindowPtr pWin; + Atom property, type; + int format, mode; + unsigned long nUnits; + pointer value; +{ + char *propertyS, *typeS; + Atom propertyX, typeX; + char *output = NULL; + XWMHints wmHints; + Bool export = False; + Bool freeMem = False; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return 0; + } + + propertyS = NameForAtom(property); + typeS = NameForAtom(type); + + if (strncmp(propertyS, "WM_", 3) != 0 && + strncmp(propertyS, "_NET_", 5) != 0 && + strcmp(propertyS, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR") != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentExportProperty: WARNING! Ignored ChangeProperty " + "on %swindow %lx property %s type %s nUnits %ld format %d\n", + nxagentWindowTopLevel(pWin) ? "toplevel " : "", nxagentWindow(pWin), + validateString(propertyS), validateString(typeS), nUnits, format); + #endif + } + else if (strcmp(typeS, "STRING") == 0 || + #ifndef _XSERVER64 + strcmp(typeS, "CARDINAL") == 0 || + strcmp(typeS, "WM_SIZE_HINTS") == 0 || + #endif + strcmp(typeS, "UTF8_STRING") == 0) + { + output = value; + export = True; + } + #ifdef _XSERVER64 + else if (strcmp(typeS, "CARDINAL") == 0 || strcmp(typeS, "WM_SIZE_HINTS") == 0) + { + unsigned long *buffer = malloc(nUnits * sizeof(*buffer)); + int *input = value; + int i; + + if (buffer) + { + freeMem = True; + export = True; + output = (char*) buffer; + + for (i = 0; i < nUnits; i++) + { + buffer[i] = input[i]; + } + } + } + #endif + else if (strcmp(typeS, "WM_HINTS") == 0) + { + ClientPtr pClient = wClient(pWin); + wmHints = *(XWMHints*)value; + + wmHints.flags |= InputHint; + wmHints.input = True; + + output = (char*) &wmHints; + export = True; + + if ((wmHints.flags & IconPixmapHint) && (wmHints.icon_pixmap != None)) + { + PixmapPtr icon = (PixmapPtr)SecurityLookupIDByType(pClient, wmHints.icon_pixmap, + RT_PIXMAP, SecurityDestroyAccess); + + if (icon) + { + if (nxagentDrawableStatus((DrawablePtr) icon) == NotSynchronized) + { + nxagentSynchronizeRegion((DrawablePtr) icon, NullRegion, NEVER_BREAK, NULL); + } + + wmHints.icon_pixmap = nxagentPixmap(icon); + } + else + { + wmHints.flags &= ~IconPixmapHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon pixmap %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.icon_pixmap, propertyS, typeS, (void*)pWin); + #endif + } + } + + if ((wmHints.flags & IconWindowHint) && (wmHints.icon_window != None)) + { + WindowPtr icon = (WindowPtr)SecurityLookupWindow(wmHints.icon_window, pClient, + SecurityDestroyAccess); + + if (icon) + { + wmHints.icon_window = nxagentWindow(icon); + } + else + { + wmHints.flags &= ~IconWindowHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon window %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.icon_window, propertyS, typeS, (void*)pWin); + #endif + } + } + + if ((wmHints.flags & IconMaskHint) && (wmHints.icon_mask != None)) + { + PixmapPtr icon = (PixmapPtr)SecurityLookupIDByType(pClient, wmHints.icon_mask, + RT_PIXMAP, SecurityDestroyAccess); + + if (icon) + { + wmHints.icon_mask = nxagentPixmap(icon); + } + else + { + wmHints.flags &= ~IconMaskHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon mask %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.icon_mask, propertyS, typeS, (void*)pWin); + #endif + } + } + + if ((wmHints.flags & WindowGroupHint) && (wmHints.window_group != None)) + { + WindowPtr window = (WindowPtr)SecurityLookupWindow(wmHints.window_group, pClient, + SecurityDestroyAccess); + + if (window) + { + wmHints.window_group = nxagentWindow(window); + } + else + { + wmHints.flags &= ~WindowGroupHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up window group %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.window_group, propertyS, typeS, (void*)pWin); + #endif + } + } + } + else if (strcmp(typeS, "ATOM") == 0) + { + XlibAtom *atoms = malloc(nUnits * sizeof(*atoms)); + Atom *input = value; + int i; + + freeMem = True; + export = True; + output = (char *) atoms; + + for (i = 0; i < nUnits; i++) + { + atoms[i] = nxagentLocalToRemoteAtom(input[i]); + + if (atoms[i] == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to convert local atom %ld [%s].\n", + (long int) input[i], validateString(NameForAtom(input[i]))); + #endif + } + } + } + else if (strcmp(typeS, "WINDOW") == 0) + { + Window *input = value; + XlibWindow *wind = malloc(nUnits * sizeof(*wind)); + ClientPtr pClient = wClient(pWin); + WindowPtr pWindow; + int i; + + freeMem = True; + export = True; + output = (char*) wind; + + for (i = 0; i < nUnits; i++) + { + pWindow = (WindowPtr)SecurityLookupWindow(input[i], pClient, + SecurityDestroyAccess); + if ((input[i] != None) && pWindow) + { + wind[i] = nxagentWindow(pWindow); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up window %ld " + "exporting property %s type %s on window %p.\n", + (long int) input[i], propertyS, typeS, (void *) pWin); + #endif + + /* + * It seems that clients specifie + * strange windows, perhaps are + * not real windows so we can try + * to let them pass anyway. + * + * wind[i] = None; + * + */ + } + } + } + + if (export) + { + propertyX = nxagentLocalToRemoteAtom(property); + typeX = nxagentLocalToRemoteAtom(type); + + if (propertyX == None || typeX == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to convert local atom.\n"); + #endif + + export = 0; + } + else + { + XChangeProperty(nxagentDisplay, nxagentWindow(pWin), propertyX, typeX, format, mode, (void*)output, nUnits); + nxagentAddPropertyToList(propertyX, pWin); + } + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentExportProperty: WARNING! Ignored ChangeProperty " + "on %swindow %lx property %s type %s nUnits %ld format %d\n", + nxagentWindowTopLevel(pWin) ? "toplevel " : "", + nxagentWindow(pWin), validateString(propertyS), validateString(typeS), + nUnits, format); + #endif + } + + if (freeMem) + { + xfree(output); + } + + return export; +} + +void nxagentImportProperty(Window window, + Atom property, + Atom type, + int format, + unsigned long nitems, + unsigned long bytes_after, + unsigned char *buffer) +{ + Atom propertyL; + Atom typeL; + + WindowPtr pWin; + Bool import = False; + Bool freeMem = False; + XWMHints wmHints; + + typedef struct { + CARD32 state; + Window icon; + } WMState; + WMState wmState; + + char *output = NULL; + char *typeS; + + pWin = nxagentWindowPtr(window); + + if (pWin == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Failed to look up remote window %lx property [%ld] exiting.\n", + window, property); + #endif + + return; + } + + propertyL = nxagentRemoteToLocalAtom(property); + + if (!ValidAtom(propertyL)) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Failed to convert remote property atom.\n"); + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Window %lx property [%ld]: %s\n", + window, property, validateString(NameForAtom(propertyL))); + #endif + + /* + * We settle a property size limit of + * 256K beyond which we simply ignore them. + */ + + typeL = nxagentRemoteToLocalAtom(type); + typeS = NameForAtom(typeL); + + if (buffer == NULL && (nitems > 0)) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: Failed to retrieve remote property [%ld] %s on Window %ld\n", + (long int) property, validateString(NameForAtom(propertyL)), (long int) window); + #endif + } + else if (bytes_after != 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: Remote property bigger than maximum limits.\n"); + #endif + } + else if (!ValidAtom(typeL)) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: Failed to convert remote atoms [%ld].\n", + (long int) type); + #endif + } + else if (nitems == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Importing void property.\n"); + #endif + + import = True; + } + else if (strcmp(typeS, "STRING") == 0 || + strcmp(typeS, "UTF8_STRING") == 0 || + strcmp(typeS, "CARDINAL") == 0 || + strcmp(typeS, "WM_SIZE_HINTS") == 0) + { + output = (char*)buffer; + import = True; + } + else if (strcmp(typeS, "WM_STATE") == 0) + { + /* + * Contents of property of type WM_STATE + * are {CARD32 state, WINDOW icon}. Only + * the icon field has to be modified before + * importing the property. + */ + + WindowPtr pIcon; + + wmState = *(WMState*)buffer; + pIcon = nxagentWindowPtr(wmState.icon); + + if (pIcon || wmState.icon == None) + { + import = True; + output = (char*) &wmState; + wmState.icon = pIcon ? nxagentWindow(pIcon) : None; + } + else if (wmState.icon) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to convert remote window %ld" + " importing property %ld of type WM_STATE", (long int) wmState.icon, + (long int) property); + #endif + } + } + else if (strcmp(typeS, "WM_HINTS") == 0) + { + wmHints = *(XWMHints*)buffer; + output = (char*) &wmHints; + import = True; + + if ((wmHints.flags & IconPixmapHint) && (wmHints.icon_pixmap != None)) + { + PixmapPtr icon = nxagentPixmapPtr(wmHints.icon_pixmap); + + if (icon) + { + wmHints.icon_pixmap = icon -> drawable.id; + } + else + { + wmHints.flags &= ~IconPixmapHint; + + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote icon " + "pixmap %ld from hint importing property [%ld] type %s on window %p.\n", + wmHints.icon_pixmap, (long int) property, typeS, (void *) pWin); + #endif + } + } + + if ((wmHints.flags & IconWindowHint) && (wmHints.icon_window =! None)) + { + WindowPtr icon = nxagentWindowPtr(wmHints.icon_window); + + if (icon) + { + wmHints.icon_window = icon -> drawable.id; + } + else + { + wmHints.flags &= ~IconWindowHint; + + #ifdef WARNING + fprintf(stderr, "nxagenImportProperty: WARNING! Failed to look up remote icon " + "window %lx from hint importing property [%ld] type %s on window %p.\n", + wmHints.icon_window, (long int) property, typeS, (void *) pWin); + #endif + } + } + + if ((wmHints.flags & IconMaskHint) && (wmHints.icon_mask =! None)) + { + PixmapPtr icon = nxagentPixmapPtr(wmHints.icon_mask); + + if (icon) + { + wmHints.icon_mask = icon -> drawable.id; + } + else + { + wmHints.flags &= ~IconMaskHint; + + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote icon " + "mask %lx from hint importing property [%ld] type %s on window %p.\n", + wmHints.icon_mask, (long int) property, typeS, (void *) pWin); + #endif + } + } + + if ((wmHints.flags & WindowGroupHint) && (wmHints.window_group != None)) + { + WindowPtr group = nxagentWindowPtr(wmHints.window_group); + + if (group) + { + wmHints.window_group = group -> drawable.id; + } + else + { + wmHints.flags &= ~WindowGroupHint; + + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote window " + "group %lx from hint importing property [%ld] type %s on window %p.\n", + wmHints.window_group, (long int) property, typeS, (void *) pWin); + #endif + } + } + } + else if (strcmp(typeS, "ATOM") == 0) + { + Atom *atoms = malloc(nitems * sizeof(Atom)); + Atom *input = (Atom*) buffer; + int i; + + if (atoms == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Malloc failed bailing out.\n"); + #endif + + return; + } + + freeMem = True; + import = True; + output = (char *) atoms; + + for (i = 0; i < nitems; i++) + { + atoms[i] = nxagentRemoteToLocalAtom(input[i]); + + if (atoms[i] == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to convert remote atom %ld.\n", + (long int) input[i]); + #endif + } + } + } + else if (strcmp(typeS, "WINDOW") == 0) + { + Window *input = (Window*) buffer; + Window *wind = malloc(nitems * sizeof(Window)); + WindowPtr pWindow; + int i; + + freeMem = True; + import = True; + output = (char*) wind; + + for (i = 0; i < nitems; i++) + { + pWindow = nxagentWindowPtr(input[i]); + + if (pWindow) + { + wind[i] = pWindow -> drawable.id; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote window %lx " + "importing property [%ld] type %s on window %p.\n", + (long int) input[i], (long int) property, typeS, (void*)pWin); + #endif + + wind[i] = None; + } + } + } + + if (import) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: ChangeProperty " + "on window %lx property [%ld] type %s nitems %ld format %d\n", + window, property, typeS, nitems, format); + #endif + + ChangeWindowProperty(pWin, propertyL, typeL, format, + PropModeReplace, nitems, output, 1); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: WARNING! Ignored ChangeProperty " + "on window %lx property [%ld] type %s ntems %ld format %d\n", + window, property, validateString(typeS), nitems, format); + #endif + } + + if (freeMem) + { + xfree(output); + } + + return; +} + +/* + * We want to import all properties changed by external clients to + * reflect properties of our internal windows but we must ignore + * all the property notify events generated by our own requests. + * For this purpose we implement a FIFO to record every change pro- + * perty request that we dispatch. In this way, when processing a + * property notify, we can distinguish between the notifications + * generated by our requests from those generated by other clients + * connected to the real X server. + */ + +struct nxagentPropertyRec{ + Window window; + Atom property; + struct nxagentPropertyRec *next; +}; + +static struct{ + struct nxagentPropertyRec *first; + struct nxagentPropertyRec *last; + int size; +} nxagentPropertyList = {NULL, NULL, 0}; + +/* + * Removing first element from list. + */ + +void nxagentRemovePropertyFromList() +{ + struct nxagentPropertyRec *tmp = nxagentPropertyList.first; + + #ifdef TEST + fprintf(stderr, "nxagentRemovePropertyFromList: Property %ld on Window %lx to list, list size is %d.\n\n", + nxagentPropertyList.first -> property, nxagentPropertyList.first -> window, + nxagentPropertyList.size); + #endif + + if (nxagentPropertyList.first) + { + nxagentPropertyList.first = nxagentPropertyList.first -> next; + + if (--nxagentPropertyList.size == 0) + { + nxagentPropertyList.last = NULL; + } + + xfree(tmp); + } +} + +/* + * Add the record to the list. + */ + +void nxagentAddPropertyToList(Atom property, WindowPtr pWin) +{ + struct nxagentPropertyRec *tmp; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return; + } + + if ((tmp = malloc(sizeof(struct nxagentPropertyRec))) == NULL) + { + FatalError("nxagentAddPropertyToList: malloc failed."); + } + + #ifdef TEST + fprintf(stderr, "nxagentAddPropertyToList: Adding record Property %ld - Window %lx[%p]" + "to list, list size is %d.\n", property, nxagentWindow(pWin), (void*) pWin, + nxagentPropertyList.size); + #endif + + tmp -> property = property; + tmp -> window = nxagentWindow(pWin); + tmp -> next = NULL; + + if (nxagentPropertyList.size == 0) + { + nxagentPropertyList.first = tmp; + } + else + { + nxagentPropertyList.last -> next = tmp; + } + + nxagentPropertyList.last = tmp; + nxagentPropertyList.size++; +} + +void nxagentFreePropertyList() +{ + while (nxagentPropertyList.size != 0) + { + nxagentRemovePropertyFromList(); + } +} + +/* + * We are trying to distinguish notify generated by + * an external client from those genarated by our + * own requests. + */ + +Bool nxagentNotifyMatchChangeProperty(void *p) +{ + struct nxagentPropertyRec *first = nxagentPropertyList.first; + XPropertyEvent *X = p; + + #ifdef TEST + fprintf(stderr, "nxagentNotifyMatchChangeProperty: Property notify on window %lx property %ld.\n", + X -> window, X -> atom); + + if (first) + { + fprintf(stderr, "nxagentNotifyMatchChangeProperty: First element on list is window %lx property %ld list size is %d.\n", + first -> window, first -> property, nxagentPropertyList.size); + } + else + { + fprintf(stderr, "nxagentNotifyMatchChangeProperty: List is empty.\n"); + } + #endif + + if (first == NULL || + X -> window != first -> window || + X -> atom != first -> property) + { + return False; + } + + nxagentRemovePropertyFromList(); + + return True; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Rootless.h b/nx-X11/programs/Xserver/hw/nxagent/Rootless.h new file mode 100644 index 000000000..90d25d0c1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Rootless.h @@ -0,0 +1,93 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Rootless_H__ +#define __Rootless_H__ + +#include "window.h" + +/* + * The real X server's root window if we + * are in rootless mode. + */ + +extern WindowPtr nxagentRootlessWindow; + +/* + * We want to import all properties changed by external clients to + * reflect properties of our internal windows but we must ignore + * all the property notify events generated by our own requests. + * For this purpose we implement a FIFO to record every change pro- + * perty request that we dispatch. In this way, when processing a + * property notify, we can distinguish between the notifications + * generated by our requests from those generated by other clients + * connected to the real X server. + */ + +typedef struct +{ + Window window; + Atom property; +} PropertyRequestRec; + +extern PropertyRequestRec nxagentPropertyRequests[256]; + +Window nxagentRootlessWindowParent(WindowPtr pWin); + +void nxagentRootlessAddTopLevelWindow(WindowPtr pWin, Window w); +void nxagentRootlessDelTopLevelWindow(WindowPtr pWin); + +WindowPtr nxagentRootlessTopLevelWindow(Window w); + +#ifndef _XSERVER64 +void nxagentRootlessRestack(Window *toplevel, unsigned int ntoplevel); +#else +void nxagentRootlessRestack(unsigned long *toplevel, unsigned int ntoplevel); +#endif + + +int nxagentExportAllProperty(WindowPtr pWin); + +int nxagentExportProperty(WindowPtr pWin, Atom property, Atom type, int format, + int mode, unsigned long nUnits, pointer value); + +#define MAX_RETRIEVED_PROPERTY_SIZE 256 * 1024 + +void nxagentImportProperty(Window window, Atom property, Atom type, int format, + unsigned long nitems, unsigned long bytes_after, unsigned char *buffer); + +/* + * Push last ChangeProperty to the list. + */ + +void nxagentAddPropertyToList(Atom property, WindowPtr pWin); + +/* + * Check if a PropertyNotify match the top + * of the list. + */ + +Bool nxagentNotifyMatchChangeProperty(void *X); + +void nxagentConfigureRootlessWindow(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib, int stack_mode, Mask mask); + +void nxagentCirculateRootlessWindows(int direction); + +void nxagentFreePropertyList(void); + +#endif /* __Rootless_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.c b/nx-X11/programs/Xserver/hw/nxagent/Screen.c new file mode 100644 index 000000000..255da3362 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.c @@ -0,0 +1,3984 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +/* + * Used by the auto-disconnect feature. + */ + +#include + +#include "scrnintstr.h" +#include "dix.h" +#include "dixstruct.h" +#include "mi.h" +#include "micmap.h" +#include "colormapst.h" +#include "resource.h" +#include "mipointer.h" +#include "../../fb/fb.h" +#include "../../randr/randrstr.h" +#include "inputstr.h" + +#include "Agent.h" +#include "Display.h" +#include "Screen.h" +#include "Extensions.h" +#include "Atoms.h" +#include "GCs.h" +#include "GCOps.h" +#include "Image.h" +#include "Drawable.h" +#include "Font.h" +#include "Colormap.h" +#include "Cursor.h" +#include "Visual.h" +#include "Events.h" +#include "Init.h" +#include "Args.h" +#include "Client.h" +#include "Options.h" +#include "Splash.h" +#include "Holder.h" +#include "Render.h" +#include "Trap.h" +#include "Keyboard.h" +#include "Pointer.h" +#include "Reconnect.h" +#include "Composite.h" +#include "Shadow.h" +#include "Utils.h" + +#include "Xrandr.h" +#include + +#include "Xatom.h" +#include "Xproto.h" + +#include "NXlib.h" + +#include "mibstorest.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef WATCH +#undef DUMP + +/* + * Display a pixmap on an shadow + * display used for debug. + */ + +#ifdef DUMP + +void nxagentShowPixmap(PixmapPtr pPixmap, int x, int y, int width, int height); + +void nxagentFbRestoreArea(PixmapPtr pPixmap, WindowPtr pWin, int xSrc, int ySrc, int width, + int height, int xDst, int yDst) +#endif + +#ifdef WATCH +#include "unistd.h" +#endif + +extern Bool nxagentIpaq; +extern Pixmap nxagentIconPixmap; +extern Pixmap nxagentIconShape; +extern Bool useXpmIcon; + +/* + * From randr/randr.c. + */ + +extern Bool RRGetInfo(ScreenPtr pScreen); +extern void RRSendConfigNotify(ScreenPtr pScreen); +extern void RREditConnectionInfo(ScreenPtr pScreen); + +Window nxagentDefaultWindows[MAXSCREENS]; +Window nxagentInputWindows[MAXSCREENS]; +Window nxagentScreenSaverWindows[MAXSCREENS]; + +#ifdef NXAGENT_ONSTART +Atom nxagentWMStart; +Window nxagentSplashWindow = None; +Pixmap nxagentPixmapLogo; +#endif + +ScreenPtr nxagentDefaultScreen = NULL; +int nxagentArgc = 0; +char **nxagentArgv = NULL; + +#ifdef NXAGENT_ARTSD + +char mcop_atom[] = "MCOPGLOBALS"; +Atom mcop_local_atom = None; +unsigned char fromHexNibble(char c); +void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port); + +#endif + +Window nxagentIconWindow = None; +Window nxagentFullscreenWindow = None; + +#ifdef VIEWPORT_FRAME + +WindowPtr nxagentViewportFrameLeft; +WindowPtr nxagentViewportFrameRight; +WindowPtr nxagentViewportFrameAbove; +WindowPtr nxagentViewportFrameBelow; + +#endif /* #ifdef VIEWPORT_FRAME */ + +Bool nxagentCreateScreenResources(ScreenPtr pScreen); +void nxagentPrintAgentGeometry(char *hdrMessage, char *prefix); + +/* + * These variables are for shadowing feature. + */ + +int nxagentShadowResize = 0; + +WindowPtr nxagentShadowWindowPtr = NULL; + +static XID accessPixmapID; +static Window accessWindowID; +static int imageByteOrder; +static unsigned char nxagentMasterDepth; +static unsigned char nxagentCheckDepth = 0; +static unsigned int nxagentBppShadow; +static unsigned int nxagentBppMaster; +int nxagentShadowXConnectionNumber; +GCPtr nxagentShadowGCPtr = NULL; +PixmapPtr nxagentShadowPixmapPtr = NULL; +char * nxagentShadowBuffer; +unsigned char nxagentShadowDepth; +int nxagentShadowWidth; +int nxagentShadowHeight; +Display * nxagentShadowDisplay; +short nxagentShadowUid = -1; + +void nxagentShadowAdaptDepth(unsigned int, unsigned int, unsigned int, char **); + +RegionRec nxagentShadowUpdateRegion; + +#define NXAGENT_DEFAULT_DPI 75 + +/* + * From randr/randr.c. This was originally static + * but we need it here. + */ + +int TellChanged(WindowPtr pWin, pointer value); + +int nxagentBitsPerPixel(int depth) +{ + if (depth == 1) return 1; + else if (depth <= 8) return 8; + else if (depth <= 16) return 16; + else return 32; +} + +void nxagentSetScreenInfo(ScreenInfo *screenInfo) +{ + /* + * Setup global screen info parameters. In the Xnest + * server this stuff is done after having opened the + * real display as Xnest lets the screen reflect the + * order of the remote end. Agent will instead set + * the order according to local endianess and swap + * data whenever it is appropriate. + * + * From a standard implementation: + * + * screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + * screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + * screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + * screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + * + * From Xnest implementation: + * + * screenInfo -> imageByteOrder = ImageByteOrder(nxagentDisplay); + * screenInfo -> bitmapScanlineUnit = BitmapUnit(nxagentDisplay); + * screenInfo -> bitmapScanlinePad = BitmapPad(nxagentDisplay); + * screenInfo -> bitmapBitOrder = BitmapBitOrder(nxagentDisplay); + */ + + screenInfo -> imageByteOrder = IMAGE_BYTE_ORDER; + screenInfo -> bitmapScanlinePad = BITMAP_SCANLINE_PAD; + screenInfo -> bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + screenInfo -> bitmapBitOrder = BITMAP_BIT_ORDER; + + #ifdef TEST + fprintf(stderr, "nxagentSetScreenInfo: Server image order is [%d] bitmap order is [%d].\n", + screenInfo -> imageByteOrder, screenInfo -> bitmapBitOrder); + + fprintf(stderr, "nxagentSetScreenInfo: Server scanline unit is [%d] scanline pad is [%d].\n", + screenInfo -> bitmapScanlineUnit, screenInfo -> bitmapScanlinePad); + #endif +} + +void nxagentSetPixmapFormats(ScreenInfo *screenInfo) +{ + int i; + + /* + * Formats are created with no care of which are supported + * on the real display. Creating only formats supported + * by the remote end makes troublesome handling migration + * of session from a display to another. + */ + + screenInfo -> numPixmapFormats = nxagentNumPixmapFormats; + + for (i = 0; i < nxagentNumPixmapFormats; i++) + { + screenInfo -> formats[i].depth = nxagentPixmapFormats[i].depth; + screenInfo -> formats[i].bitsPerPixel = nxagentPixmapFormats[i].bits_per_pixel; + screenInfo -> formats[i].scanlinePad = nxagentPixmapFormats[i].scanline_pad; + + #ifdef TEST + fprintf(stderr, "nxagentSetPixmapFormats: Set format at index [%d] to depth [%d] " + "bits per pixel [%d] scanline pad [%d].\n", i, + screenInfo -> formats[i].depth, screenInfo -> formats[i].bitsPerPixel, + screenInfo -> formats[i].scanlinePad); + #endif + } +} + +void nxagentMinimizeFromFullScreen(ScreenPtr pScreen) +{ + XUnmapWindow(nxagentDisplay, nxagentFullscreenWindow); + + if(nxagentIpaq) + { + XMapWindow(nxagentDisplay, nxagentIconWindow); + XIconifyWindow(nxagentDisplay, nxagentIconWindow, + DefaultScreen(nxagentDisplay)); + } + else + { + XIconifyWindow(nxagentDisplay, nxagentIconWindow, + DefaultScreen(nxagentDisplay)); + } +} + +void nxagentMaximizeToFullScreen(ScreenPtr pScreen) +{ + if(nxagentIpaq) + { + XUnmapWindow(nxagentDisplay, nxagentIconWindow); + + XMapWindow(nxagentDisplay, nxagentFullscreenWindow); + } + else + { +/* + XUnmapWindow(nxagentDisplay, nxagentIconWindow); +*/ + XMapRaised(nxagentDisplay, nxagentFullscreenWindow); + + XIconifyWindow(nxagentDisplay, nxagentIconWindow, + DefaultScreen(nxagentDisplay)); +/* + XMapWindow(nxagentDisplay, nxagentIconWindow); +*/ + } +} + +Window nxagentCreateIconWindow() +{ + XSetWindowAttributes attributes; + unsigned long valuemask; + char* window_name; + XTextProperty windowName; + XSizeHints sizeHints; + XWMHints wmHints; + Window w; + Mask mask; + + /* + * Create icon window. + */ + + attributes.override_redirect = False; + attributes.colormap = DefaultColormap(nxagentDisplay, DefaultScreen(nxagentDisplay)); + attributes.background_pixmap = nxagentScreenSaverPixmap; + valuemask = CWOverrideRedirect | CWBackPixmap | CWColormap; + + #ifdef TEST + fprintf(stderr, "nxagentCreateIconWindow: Going to create new icon window.\n"); + #endif + + w = XCreateWindow(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + 0, 0, 1, 1, 0, + DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)), + InputOutput, + DefaultVisual(nxagentDisplay, DefaultScreen(nxagentDisplay)), + valuemask, &attributes); + + #ifdef TEST + fprintf(stderr, "nxagentCreateIconWindow: Created new icon window with id [%ld].\n", + nxagentIconWindow); + #endif + + /* + * Set hints to the window manager for the icon window. + */ + + window_name = nxagentWindowName; + XStringListToTextProperty(&window_name, 1, &windowName); + sizeHints.flags = PMinSize | PMaxSize; + sizeHints.min_width = sizeHints.max_width = 1; + sizeHints.min_height = sizeHints.max_height = 1; + wmHints.flags = IconPixmapHint | IconMaskHint; + wmHints.initial_state = IconicState; + wmHints.icon_pixmap = nxagentIconPixmap; + + if (useXpmIcon) + { + wmHints.icon_mask = nxagentIconShape; + wmHints.flags = IconPixmapHint | IconMaskHint; + } + else + { + wmHints.flags = StateHint | IconPixmapHint; + } + + XSetWMProperties(nxagentDisplay, w, + &windowName, &windowName, + NULL , 0 , &sizeHints, &wmHints, NULL); + + /* + * Enable events from the icon window. + */ + + nxagentGetDefaultEventMask(&mask); + + XSelectInput(nxagentDisplay, w, (mask & ~(KeyPressMask | + KeyReleaseMask)) | StructureNotifyMask); + + /* + * Notify to client if user closes icon window. + */ + + if (nxagentWMIsRunning && !nxagentOption(Rootless)) + { + XlibAtom deleteWMAtom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */ + + XSetWMProtocols(nxagentDisplay, w, &deleteWMAtom, 1); + } + + return w; +} + +Bool nxagentMagicPixelZone(int x, int y) +{ + return (x >= nxagentOption(Width) - 1 && y < 1); +} + +void nxagentSetScreenSaverTime(void) +{ + #ifdef TEST + fprintf(stderr, "nxagentSetScreenSaverTime: ScreenSaverTime was [%lu], ScreenSaverInterval was [%lu].\n", + ScreenSaverTime, ScreenSaverInterval); + #endif + + /* + * More than one timeout could be used here, + * to make use of screen-saver handler not + * only for the timeout feature. In a case + * like this, the lower timeout have to be + * used as ScreenSaverTime. + */ + + if (nxagentAutoDisconnectTimeout > 0) + { + ScreenSaverTime = nxagentAutoDisconnectTimeout; + } + + ScreenSaverInterval = ScreenSaverTime; + + #ifdef TEST + fprintf(stderr, "nxagentSetScreenSaverTime: ScreenSaverTime now is [%lu], ScreenSaverInterval now is [%lu].\n", + ScreenSaverTime, ScreenSaverInterval); + #endif +} + +static Bool nxagentSaveScreen(ScreenPtr pScreen, int what) +{ + #ifdef TEST + fprintf(stderr, "nxagentSaveScreen: Called for screen at [%p] with parameter [%d].\n", + (void *) pScreen, what); + + fprintf(stderr, "nxagentSaveScreen: SCREEN_SAVER_ON is [%d] SCREEN_SAVER_OFF is [%d] " + "SCREEN_SAVER_FORCER is [%d] SCREEN_SAVER_CYCLE is [%d].\n", + SCREEN_SAVER_ON, SCREEN_SAVER_OFF, SCREEN_SAVER_FORCER, + SCREEN_SAVER_CYCLE); + #endif + + /* + * We need only to reset the timeouts + * in this case. + */ + + if (what == SCREEN_SAVER_OFF) + { + nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND; + + return 1; + } + + /* + * The lastDeviceEventTime is updated every time + * a device event is received, and it is used by + * WaitForSomething() to know when the SaveScreens() + * function should be called. This solution doesn't + * take care of a pointer button not released, so + * we have to handle this case by ourselves. + */ + +/* +FIXME: Do we need to check the key grab if the + autorepeat feature is disabled? +*/ + if (inputInfo.pointer -> button -> buttonsDown > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSaveScreen: Ignoring timeout, there is a pointer button down.\n"); + #endif + + /* + * Returning 0 the SaveScreens() function + * (which calls this one) tries to build + * a screen-saver creating a new window. + * We don't want this, so we return 1 in + * any case. + */ + + return 1; + } + + /* + * Handling the auto-disconnect feature. + * If there is any client attached and the persisten- + * ce is allowed then leave the session running, else + * terminate it. It should use something less brutal, + * though raising a signal should ensure that the code + * follows the usual execution path. + */ + + if (nxagentOption(Timeout) > 0) + { + #ifdef TEST + fprintf(stderr, "nxagentSaveScreen: Auto-disconnect timeout was [%d].\n", + nxagentAutoDisconnectTimeout); + #endif + + nxagentAutoDisconnectTimeout -= ScreenSaverTime; + + #ifdef TEST + fprintf(stderr, "nxagentSaveScreen: Auto-disconnect timeout is [%d].\n", + nxagentAutoDisconnectTimeout); + #endif + + if (nxagentSessionState == SESSION_UP && + nxagentAutoDisconnectTimeout <= 0) + { + nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND; + + if (nxagentClients == 0) + { + fprintf(stderr, "Info: Terminating session with no client running.\n"); + + raise(SIGTERM); + } + else if (nxagentOption(Persistent) == 0) + { + fprintf(stderr, "Info: Terminating session with persistence not allowed.\n"); + + raise(SIGTERM); + } + else + { + fprintf(stderr, "Info: Suspending session with %d clients running.\n", + nxagentClients); + + raise(SIGHUP); + } + } + } + + return 1; +} + +Bool nxagentCreateScreenResources(ScreenPtr pScreen) +{ + Bool ret; + + CreatePixmapProcPtr savedCreatePixmap = pScreen->CreatePixmap; + ModifyPixmapHeaderProcPtr savedModifyPixmapHeader = pScreen->ModifyPixmapHeader; + + pScreen->CreatePixmap = fbCreatePixmap; + pScreen->ModifyPixmapHeader = miModifyPixmapHeader; + ret = miCreateScreenResources(pScreen); + + pScreen->CreatePixmap = savedCreatePixmap; + pScreen->ModifyPixmapHeader = savedModifyPixmapHeader; + + return ret; +} + +static Bool nxagentCursorOffScreen(ScreenPtr *pPtrScreen, int *x, int *y) +{ + return False; +} + +static void nxagentCrossScreen(ScreenPtr pScreen, Bool entering) +{ +} + +static miPointerScreenFuncRec nxagentPointerCursorFuncs = +{ + nxagentCursorOffScreen, + nxagentCrossScreen, + miPointerWarpCursor +}; + +#ifdef VIEWPORT_FRAME + +void nxagentInitViewportFrame(ScreenPtr pScreen, WindowPtr pRootWin) +{ + int error = Success; + VisualID visual = 0; + int i; + XID xid; + + if (nxagentOption(Rootless)) + { + return; + } + + for (i = 0; i < pScreen -> numDepths; i++) + { + if (pScreen -> allowedDepths[i].depth == pRootWin -> drawable.depth) + { + visual = pScreen -> allowedDepths[i].vids[0]; + break; + } + } + + /* + * It is not necessary create the windows on the real X server. But this + * windows are not visible. Create them it is not a great effort, and avoids + * many errors. + * + * nxagentScreenTrap = True; + */ + + xid = FakeClientID(serverClient -> index); + + #ifdef TEST + fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid); + #endif + + nxagentViewportFrameLeft = CreateWindow(xid, pRootWin, -NXAGENT_FRAME_WIDTH, 0, NXAGENT_FRAME_WIDTH, + pRootWin -> drawable.height, + 0, InputOutput, 0, NULL, + pRootWin -> drawable.depth, + serverClient, visual, &error); + + AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameLeft); + + if (error != Success) + { + #ifdef WARNING + fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameLeft.\n"); + #endif + + error = Success; + } + + xid = FakeClientID(serverClient -> index); + + #ifdef TEST + fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid); + #endif + + nxagentViewportFrameRight = CreateWindow(xid, pRootWin, pRootWin -> drawable.width, 0, + NXAGENT_FRAME_WIDTH, + pRootWin -> drawable.height, + 0, InputOutput, 0, NULL, + pRootWin -> drawable.depth, + serverClient, visual, + &error); + + AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameRight); + + if (error != Success) + { + #ifdef WARNING + fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameRight.\n"); + #endif + + error = Success; + } + + xid = FakeClientID(serverClient -> index); + + #ifdef TEST + fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid); + #endif + + nxagentViewportFrameAbove = CreateWindow(xid, pRootWin, 0, -NXAGENT_FRAME_WIDTH, + pRootWin -> drawable.width, + NXAGENT_FRAME_WIDTH, 0, + InputOutput, 0, NULL, + pRootWin -> drawable.depth, + serverClient, visual, + &error); + + AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameAbove); + + if (error != Success) + { + #ifdef WARNING + fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameAbove.\n"); + #endif + + error = Success; + } + + xid = FakeClientID(serverClient -> index); + + #ifdef TEST + fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid); + #endif + + nxagentViewportFrameBelow = CreateWindow(xid, pRootWin, 0, + pRootWin -> drawable.height, + pRootWin -> drawable.width, + NXAGENT_FRAME_WIDTH, 0, + InputOutput, 0, NULL, + pRootWin -> drawable.depth, + serverClient, visual, &error); + + AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameBelow); + + if (error != Success) + { + #ifdef WARNING + fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameBelow.\n"); + #endif + } + + nxagentViewportFrameLeft -> overrideRedirect = 1; + nxagentViewportFrameRight -> overrideRedirect = 1; + nxagentViewportFrameAbove -> overrideRedirect = 1; + nxagentViewportFrameBelow -> overrideRedirect = 1; + + MapWindow(nxagentViewportFrameLeft, serverClient); + MapWindow(nxagentViewportFrameRight, serverClient); + MapWindow(nxagentViewportFrameAbove, serverClient); + MapWindow(nxagentViewportFrameBelow, serverClient); + + /* + * nxagentScreenTrap = False; + */ +} + +#endif /* #ifdef VIEWPORT_FRAME */ + +void nxagentPrintAgentGeometry(char *hdrMessage, char *prefix) +{ + #ifdef WARNING + + if (prefix == NULL) + { + prefix = ""; + } + + if (hdrMessage) + { + fprintf(stderr, "--------------- %s -----------------.\n", hdrMessage); + } + + fprintf(stderr, "%s Root window at offset (%d,%d) size (%d,%d).\n", prefix, + nxagentOption(RootX), nxagentOption(RootY), + nxagentOption(RootWidth), nxagentOption(RootHeight)); + + fprintf(stderr, "%s Default window at offset (%d,%d) size (%d,%d) border size %d.\n", prefix, + nxagentOption(X), nxagentOption(Y), nxagentOption(Width), nxagentOption(Height), + nxagentOption(BorderWidth)); + + fprintf(stderr, "%s Span between root window and default window is (%d,%d).\n", prefix, + nxagentOption(ViewportXSpan), nxagentOption(ViewportYSpan)); + + fprintf(stderr, "%s Default window in window mode has offset (%d,%d) and size (%d,%d).\n", prefix, + nxagentOption(SavedX), nxagentOption(SavedY), nxagentOption(SavedWidth), nxagentOption(SavedHeight)); + + fprintf(stderr, "%s Fullscreen is %s.\n", prefix, + nxagentOption(Fullscreen) ? "ON" : "OFF"); + + fprintf(stderr, "%s Desktop resize mode is %s.\n", prefix, + nxagentOption(DesktopResize) ? "ON" : "OFF"); + + fprintf(stderr, "%s Resize desktop at startup is %s.\n", prefix, + nxagentResizeDesktopAtStartup ? "ON" : "OFF"); + + #endif +} + +static int nxagentColorOffset(unsigned long mask) +{ + int count; + + for (count = 0; !(mask & 1) && count < 32; count++) + { + mask >>= 1; + } + + return count; +} + +Bool nxagentOpenScreen(int index, ScreenPtr pScreen, + int argc, char *argv[]) +{ + VisualPtr visuals; + DepthPtr depths; + int numVisuals, numDepths; + int i, j, depthIndex; + unsigned long valuemask; + XSetWindowAttributes attributes; + XWindowAttributes gattributes; + XSizeHints sizeHints; + XWMHints wmHints; + Mask mask; + Bool resetAgentPosition = False; + + VisualID defaultVisual; + int rootDepth; + + pointer pFrameBufferBits; + int bitsPerPixel; + int sizeInBytes; + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Called for screen index [%d].\n", + index); + #endif + + if (nxagentRenderEnable && nxagentReconnectTrap == False) + { + PictureScreenPrivateIndex = -1; + } + + nxagentDefaultScreen = pScreen; + + nxagentQueryAtoms(pScreen); + + #ifdef NXAGENT_ONSTART + nxagentWMStart = nxagentAtoms[3]; /* WM_NX_READY */ + #endif + + /* + * Forced geometry parameter + * to user geometry. + */ + + if (nxagentResizeDesktopAtStartup) + { + if (nxagentUserGeometry.flag & XValue) + { + nxagentChangeOption(X, nxagentUserGeometry.X); + } + + if (nxagentUserGeometry.flag & YValue) + { + nxagentChangeOption(Y, nxagentUserGeometry.Y); + } + + if (nxagentUserGeometry.flag & WidthValue) + { + nxagentChangeOption(Width, nxagentUserGeometry.Width); + nxagentChangeOption(RootWidth, nxagentUserGeometry.Width); + + if (nxagentOption(SavedWidth) > nxagentUserGeometry.Width) + { + nxagentChangeOption(SavedWidth, nxagentUserGeometry.Width); + } + } + + if (nxagentUserGeometry.flag & HeightValue) + { + nxagentChangeOption(Height, nxagentUserGeometry.Height); + nxagentChangeOption(RootHeight, nxagentUserGeometry.Height); + + if (nxagentOption(SavedHeight) > nxagentUserGeometry.Height) + { + nxagentChangeOption(SavedHeight, nxagentUserGeometry.Height); + } + } + } + + /* + * This is first time the + * screen is initialized. + * Filling the geometry parameter + * from user geometry. + */ + + if (nxagentReconnectTrap == False) + { + if (nxagentUserGeometry.flag & XValue) + { + nxagentChangeOption(X, nxagentUserGeometry.X); + } + + if (nxagentUserGeometry.flag & YValue) + { + nxagentChangeOption(Y, nxagentUserGeometry.Y); + } + + if (nxagentUserGeometry.flag & WidthValue) + { + nxagentChangeOption(RootWidth, nxagentUserGeometry.Width); + } + + if (nxagentUserGeometry.flag & HeightValue) + { + nxagentChangeOption(RootHeight, nxagentUserGeometry.Height); + } + } + else if (nxagentWMIsRunning && !nxagentOption(Rootless) && !nxagentOption(Fullscreen)) + { + /* + * At reconnection, try to estimate the shift due to WM reparenting. + */ + + if (nxagentOption(X) >= 6) + { + nxagentChangeOption(X, nxagentOption(X) - 6); + } + + if (nxagentOption(Y) >= 25) + { + nxagentChangeOption(Y, nxagentOption(Y) - 25); + } + } + + /* + * Determine the size of the root window. + * It is the maximum size of the screen + * if we are either in rootless or in + * fullscreen mode. + */ + + if (nxagentOption(Rootless) == False && nxagentWMIsRunning == False) + { + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Forcing fullscreen mode with no window manager running.\n"); + #endif + + nxagentChangeOption(Fullscreen, True); + + if (nxagentOption(ClientOs) == ClientOsWinnt) + { + NXSetExposeParameters(nxagentDisplay, 0, 0, 0); + } + } + + if (nxagentOption(Fullscreen) && + nxagentWMIsRunning && + nxagentReconnectTrap && + nxagentResizeDesktopAtStartup == False && + nxagentXServerGeometryChanged()) + { + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Forcing window mode with server geometry changed.\n"); + #endif + + nxagentChangeOption(Fullscreen, False); + + resetAgentPosition = True; + } + + if (nxagentOption(Fullscreen)) + { + nxagentChangeOption(X, 0); + nxagentChangeOption(Y, 0); + + nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + + nxagentChangeOption(BorderWidth, 0); + + if (nxagentReconnectTrap == False || nxagentResizeDesktopAtStartup) + { + nxagentChangeOption(RootWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + nxagentChangeOption(RootHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + + if (nxagentOption(RootWidth) > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) + { + nxagentChangeOption(SavedWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4); + } + else + { + nxagentChangeOption(SavedWidth, nxagentOption(RootWidth)); + } + + if (nxagentOption(RootHeight) > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) + { + nxagentChangeOption(SavedHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4); + } + else + { + nxagentChangeOption(SavedHeight, nxagentOption(RootHeight)); + } + } + + nxagentChangeOption(RootX, ((WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) - + nxagentOption(RootWidth)) / 2)); + nxagentChangeOption(RootY, ((HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) - + nxagentOption(RootHeight)) / 2)); + } + else + { + nxagentChangeOption(BorderWidth, 0); + + if (nxagentReconnectTrap == False) + { + nxagentChangeOption(RootX, 0); + nxagentChangeOption(RootY, 0); + + nxagentChangeOption(Width, nxagentOption(RootWidth)); + nxagentChangeOption(Height, nxagentOption(RootHeight)); + } + + /* + * Be sure that the agent window won't be bigger + * than the root window. + */ + + if (nxagentOption(Width) > nxagentOption(RootWidth)) + { + nxagentChangeOption(Width, nxagentOption(RootWidth)); + } + + if (nxagentOption(Height) > nxagentOption(RootHeight)) + { + nxagentChangeOption(Height, nxagentOption(RootHeight)); + } + + /* + * Be sure that the agent window won't be bigger + * than the X server root window. + */ + + if (nxagentOption(Width) > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) + { + nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4); + } + + if (nxagentOption(Height) > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) + { + nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4); + } + + /* + * Forcing the agent window geometry to be equal to + * the root window geometry the first time the + * screen is initialized if the geometry hasn't been + * esplicitly set in the option file and if + * the root window isn't bigger than the X server + * root window.. + */ + + if (nxagentReconnectTrap == False) + { + if ((nxagentOption(RootWidth) < WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) && + !(nxagentUserGeometry.flag & WidthValue)) + { + nxagentChangeOption(Width, nxagentOption(RootWidth)); + } + + if ((nxagentOption(RootHeight) < HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) && + !(nxagentUserGeometry.flag & HeightValue)) + { + nxagentChangeOption(Height, nxagentOption(RootHeight)); + } + } + + if (resetAgentPosition) + { + nxagentChangeOption(X, ((WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) - + nxagentOption(Width)) / 2)); + + nxagentChangeOption(Y, ((HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) - + nxagentOption(Height)) / 2)); + } + + nxagentChangeOption(SavedWidth, nxagentOption(RootWidth)); + nxagentChangeOption(SavedHeight, nxagentOption(RootHeight)); + } + + if (nxagentOption(Rootless)) + { + nxagentChangeOption(RootWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + nxagentChangeOption(RootHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + } + + nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth)); + nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight)); + + nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth)); + nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight)); + + if (nxagentReconnectTrap == 0) + { + if (nxagentOption(Persistent)) + { + nxagentArgc = argc; + nxagentArgv = argv; + } + + #ifdef NXAGENT_TIMESTAMP + + { + extern unsigned long startTime; + + fprintf(stderr, "Screen: going to open screen, time is [%d] milliseconds.\n", + GetTimeInMillis() - startTime); + } + + #endif + + /* + * Initialize all our privates. + */ + + if (AllocateWindowPrivate(pScreen, nxagentWindowPrivateIndex, sizeof(nxagentPrivWindowRec)) == 0 || + AllocateGCPrivate(pScreen, nxagentGCPrivateIndex, sizeof(nxagentPrivGC)) == 0 || + AllocateClientPrivate(nxagentClientPrivateIndex, sizeof(PrivClientRec)) == 0 || + AllocatePixmapPrivate(pScreen, nxagentPixmapPrivateIndex, sizeof(nxagentPrivPixmapRec)) == 0) + { + return False; + } + + /* + * Initialize the depths. + */ + + depths = (DepthPtr) xalloc(nxagentNumDepths * sizeof(DepthRec)); + + for (i = 0; i < nxagentNumDepths; i++) + { + depths[i].depth = nxagentDepths[i]; + depths[i].numVids = 0; + depths[i].vids = (VisualID *) xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); + } + + /* + * Initialize the visuals. + */ + + numVisuals = 0; + numDepths = nxagentNumDepths; + + visuals = (VisualPtr) xalloc(nxagentNumVisuals * sizeof(VisualRec)); + + for (i = 0; i < nxagentNumVisuals; i++) + { + visuals[numVisuals].vid = FakeClientID(0); + visuals[numVisuals].class = nxagentVisuals[i].class; + visuals[numVisuals].bitsPerRGBValue = nxagentVisuals[i].bits_per_rgb; + visuals[numVisuals].ColormapEntries = nxagentVisuals[i].colormap_size; + visuals[numVisuals].nplanes = nxagentVisuals[i].depth; + visuals[numVisuals].redMask = nxagentVisuals[i].red_mask; + visuals[numVisuals].greenMask = nxagentVisuals[i].green_mask; + visuals[numVisuals].blueMask = nxagentVisuals[i].blue_mask; + visuals[numVisuals].offsetRed = nxagentColorOffset(nxagentVisuals[i].red_mask); + visuals[numVisuals].offsetGreen = nxagentColorOffset(nxagentVisuals[i].green_mask); + visuals[numVisuals].offsetBlue = nxagentColorOffset(nxagentVisuals[i].blue_mask); + + /* + * Check for and remove the duplicates. + */ + + for (j = 0; j < numVisuals; j++) + { + if (visuals[numVisuals].class == visuals[j].class && + visuals[numVisuals].bitsPerRGBValue == visuals[j].bitsPerRGBValue && + visuals[numVisuals].ColormapEntries == visuals[j].ColormapEntries && + visuals[numVisuals].nplanes == visuals[j].nplanes && + visuals[numVisuals].redMask == visuals[j].redMask && + visuals[numVisuals].greenMask == visuals[j].greenMask && + visuals[numVisuals].blueMask == visuals[j].blueMask && + visuals[numVisuals].offsetRed == visuals[j].offsetRed && + visuals[numVisuals].offsetGreen == visuals[j].offsetGreen && + visuals[numVisuals].offsetBlue == visuals[j].offsetBlue) + break; + } + + if (j < numVisuals) + continue; + + depthIndex = UNDEFINED; + + for (j = 0; j < numDepths; j++) + { + if (depths[j].depth == nxagentVisuals[i].depth) + { + depthIndex = j; + break; + } + } + + if (depthIndex == UNDEFINED) + { + #ifdef WARNING + fprintf(stderr, "nxagentOpenScreen: WARNING! Can't find a matching depth for visual depth [%d].\n", + nxagentVisuals[i].depth); + #endif + + depthIndex = numDepths; + + depths[depthIndex].depth = nxagentVisuals[i].depth; + depths[depthIndex].numVids = 0; + depths[depthIndex].vids = (VisualID *) xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); + + numDepths++; + } + + if (depths[depthIndex].numVids >= MAXVISUALSPERDEPTH) + { + FatalError("Visual table overflow"); + } + + depths[depthIndex].vids[depths[depthIndex].numVids] = visuals[numVisuals].vid; + + depths[depthIndex].numVids++; + + numVisuals++; + } + + defaultVisual = visuals[nxagentDefaultVisualIndex].vid; + rootDepth = visuals[nxagentDefaultVisualIndex].nplanes; + + nxagentInitAlphaVisual(); + + bitsPerPixel = nxagentBitsPerPixel(rootDepth); + + if (bitsPerPixel == 1) + { + sizeInBytes = PixmapBytePad(nxagentOption(RootWidth), rootDepth) * nxagentOption(RootHeight); + } + else + { + sizeInBytes = PixmapBytePad(nxagentOption(RootWidth), rootDepth) * nxagentOption(RootHeight) * bitsPerPixel/8; + } + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Frame buffer allocated. rootDepth " + "[%d] bitsPerPixel [%d] sizeInBytes [%d]\n", rootDepth, bitsPerPixel, sizeInBytes); + #endif + + pFrameBufferBits = (char *) Xalloc(sizeInBytes); + + if (!pFrameBufferBits) + { + return FALSE; + } + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Before fbScreenInit numVisuals [%d] numDepths [%d] " + "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths, + rootDepth, defaultVisual); + #endif + + if (monitorResolution < 1) + { + monitorResolution = NXAGENT_DEFAULT_DPI; + } + + if (!fbScreenInit(pScreen, pFrameBufferBits, nxagentOption(RootWidth), nxagentOption(RootHeight), + monitorResolution, monitorResolution, PixmapBytePad(nxagentOption(RootWidth), rootDepth), bitsPerPixel)) + { + return FALSE; + } + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: After fbScreenInit numVisuals [%d] numDepths [%d] " + "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths, + rootDepth, defaultVisual); + #endif + + /* + * Complete the initialization of the GLX + * extension. This will add the GLX visuals + * and will modify numVisuals and numDepths. + */ + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Before GLX numVisuals [%d] numDepths [%d] " + "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths, + rootDepth, defaultVisual); + #endif + + nxagentInitGlxExtension(&visuals, &depths, &numVisuals, &numDepths, + &rootDepth, &defaultVisual); + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: After GLX numVisuals [%d] numDepths [%d] " + "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths, + rootDepth, defaultVisual); + #endif + + /* + * Replace the visuals and depths initialized + * by fbScreenInit with our own. + */ + + xfree(pScreen -> visuals); + xfree(pScreen -> allowedDepths); + + pScreen -> visuals = visuals; + pScreen -> allowedDepths = depths; + pScreen -> numVisuals = numVisuals; + pScreen -> numDepths = numDepths; + pScreen -> rootVisual = defaultVisual; + pScreen -> rootDepth = rootDepth; + + /* + * Complete the initialization of the RANDR + * extension. + */ + + nxagentInitRandRExtension(pScreen); + + /* + * Set up the internal structures used for + * tracking the proxy resources associated + * to the unpack and split operations. + */ + + nxagentInitSplitResources(); + nxagentInitUnpackResources(); + + /* + * Initializing the pixmaps that will serve as + * "placeholders" in lazy encoding. We need one + * pixmap for each depth. + */ + + for (i = 0; i < numDepths; i++) + { + nxagentMarkPlaceholderNotLoaded(i); + } + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenScreen: Watchpoint 7.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +N/A +*/ + + sleep(30); + + #endif + + if (nxagentParentWindow != 0) + { + /* + * This would cause a GetWindowAttributes + * and a GetGeometry (asynchronous) reply. + */ + + XGetWindowAttributes(nxagentDisplay, nxagentParentWindow, &gattributes); + + nxagentChangeOption(Width, gattributes.width); + nxagentChangeOption(Height, gattributes.height); + } + + if (nxagentOption(Fullscreen)) + { + attributes.override_redirect = True; + + /* + * We need to disable the host's screensaver or + * it will otherwise grab the screen even if it + * is under agent's control. + */ + + XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking); + } + + if (nxagentTrue24) + { + fbGetScreenPrivate(pScreen) -> win32bpp = visuals[nxagentDefaultVisualIndex].nplanes; + fbGetScreenPrivate(pScreen) -> pix32bpp = visuals[nxagentDefaultVisualIndex].nplanes; + } + else + { + fbGetScreenPrivate(pScreen) -> win32bpp = 32; + fbGetScreenPrivate(pScreen) -> pix32bpp = 32; + } + + /* + * We call miScreenInit with NULL in place of the screen area if we + * don't want to initialize the frame buffer. + * + * if (!miScreenInit(pScreen, NULL, nxagentOption(RootWidth), + * nxagentOption(RootHeight), 1, 1, nxagentOption(RootWidth), + * visuals[nxagentDefaultVisualIndex].nplanes, / * Root depth. * / + * numDepths, depths, + * visuals[nxagentDefaultVisualIndex].vid,* Root visual. * / + * numVisuals, visuals)) + * return FALSE; + */ + + pScreen->defColormap = (Colormap) FakeClientID(0); + pScreen->minInstalledCmaps = MINCMAPS; + pScreen->maxInstalledCmaps = MAXCMAPS; + + pScreen->whitePixel = nxagentWhitePixel; + pScreen->blackPixel = nxagentBlackPixel; + /* rgf */ + /* GCperDepth */ + /* PixmapPerDepth */ + /* WindowPrivateLen */ + /* WindowPrivateSizes */ + /* totalWindowSize */ + /* GCPrivateLen */ + /* GCPrivateSizes */ + /* totalGCSize */ + + /* + * Random screen procedures. + */ + + pScreen->CloseScreen = nxagentCloseScreen; + pScreen->QueryBestSize = nxagentQueryBestSize; + pScreen->SaveScreen = nxagentSaveScreen; + pScreen->GetImage = nxagentGetImage; + pScreen->GetSpans = nxagentGetSpans; + pScreen->PointerNonInterestBox = (void (*)()) 0; + pScreen->SourceValidate = (void (*)()) 0; + + pScreen->CreateScreenResources = nxagentCreateScreenResources; + + /* + * Window Procedures. + * + * Note that the following functions are not + * replaced with nxagent counterparts: + * + * ValidateTreeProcPtr ValidateTree; + * ClearToBackgroundProcPtr ClearToBackground; + * + * Note also that the ConfigureWindow procedure + * has not a pointer in the screen structure. + */ + + pScreen->CreateWindow = nxagentCreateWindow; + pScreen->DestroyWindow = nxagentDestroyWindow; + pScreen->PositionWindow = nxagentPositionWindow; + pScreen->ChangeWindowAttributes = nxagentChangeWindowAttributes; + pScreen->RealizeWindow = nxagentRealizeWindow; + pScreen->UnrealizeWindow = nxagentUnrealizeWindow; + pScreen->PostValidateTree = nxagentPostValidateTree; + pScreen->WindowExposures = nxagentWindowExposures; + pScreen->PaintWindowBackground = nxagentPaintWindowBackground; + pScreen->PaintWindowBorder = nxagentPaintWindowBorder; + pScreen->CopyWindow = nxagentCopyWindow; + pScreen->ClipNotify = nxagentClipNotify; + pScreen->RestackWindow = nxagentRestackWindow; + pScreen->ReparentWindow = nxagentReparentWindow; + + /* + * Pixmap procedures. + */ + + pScreen->CreatePixmap = nxagentCreatePixmap; + pScreen->DestroyPixmap = nxagentDestroyPixmap; + + /* + * This is originally miModifyPixmapHeader() + * from miscrinit.c. It is used to recycle + * the scratch pixmap for this screen. + */ + + pScreen->ModifyPixmapHeader = nxagentModifyPixmapHeader; + + /* + * Font procedures. + */ + + pScreen->RealizeFont = nxagentRealizeFont; + pScreen->UnrealizeFont = nxagentUnrealizeFont; + + /* + * GC procedures. + */ + + pScreen->CreateGC = nxagentCreateGC; + pScreen->BitmapToRegion = nxagentPixmapToRegion; + + /* + * Colormap procedures. + */ + + pScreen->CreateColormap = nxagentCreateColormap; + pScreen->DestroyColormap = nxagentDestroyColormap; + pScreen->InstallColormap = nxagentInstallColormap; + pScreen->UninstallColormap = nxagentUninstallColormap; + pScreen->ListInstalledColormaps = nxagentListInstalledColormaps; + pScreen->StoreColors = nxagentStoreColors; + pScreen->ResolveColor = nxagentResolveColor; + + /* + * Backing store procedures. + */ + + pScreen->SaveDoomedAreas = (void (*)()) 0; + pScreen->RestoreAreas = (RegionPtr (*)()) 0; + pScreen->ExposeCopy = (void (*)()) 0; + pScreen->TranslateBackingStore = (RegionPtr (*)()) 0; + pScreen->ClearBackingStore = (RegionPtr (*)()) 0; + pScreen->DrawGuarantee = (void (*)()) 0; + + if (enableBackingStore == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Going to initialize backing store.\n"); + #endif + + pScreen -> BackingStoreFuncs.SaveAreas = nxagentSaveAreas; + pScreen -> BackingStoreFuncs.RestoreAreas = nxagentRestoreAreas; + pScreen -> BackingStoreFuncs.SetClipmaskRgn = 0; + pScreen -> BackingStoreFuncs.GetImagePixmap = 0; + pScreen -> BackingStoreFuncs.GetSpansPixmap = 0; + + miInitializeBackingStore(pScreen); + } + + /* + * OS layer procedures. + */ + + pScreen->BlockHandler = (ScreenBlockHandlerProcPtr) NoopDDA; + pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr) NoopDDA; + pScreen->blockData = NULL; + pScreen->wakeupData = NULL; + + #ifdef RENDER + + /* + * Initialize picture support. This have to be + * placed here because miDCInitialize calls + * DamageSetup, that should wrap the picture + * screen functions. So PictureInit has to be + * called before. + */ + + if (nxagentRenderEnable && !nxagentReconnectTrap) + { + if (!nxagentPictureInit(pScreen, 0, 0)) + { + nxagentRenderEnable = False; + + return FALSE; + } + + if (nxagentAlphaEnabled) + { + fprintf(stderr, "Info: Using alpha channel in render extension.\n"); + } + } + + #endif /* RENDER */ + + /* + * From misprite.c: called from device-dependent screen + * initialization proc after all of the function pointers + * have been stored in the screen structure. + */ + + miDCInitialize(pScreen, &nxagentPointerCursorFuncs); + + /* + * Cursor Procedures. + */ + + pScreen->ConstrainCursor = nxagentConstrainCursor; + pScreen->CursorLimits = nxagentCursorLimits; + pScreen->DisplayCursor = nxagentDisplayCursor; + pScreen->RealizeCursor = nxagentRealizeCursor; + pScreen->UnrealizeCursor = nxagentUnrealizeCursor; + pScreen->RecolorCursor = nxagentRecolorCursor; + pScreen->SetCursorPosition = nxagentSetCursorPosition; + + #define POSITION_OFFSET (pScreen->myNum * (nxagentOption(Width) + \ + nxagentOption(Height)) / 32) + } + + #ifdef TEST + nxagentPrintAgentGeometry(NULL, "nxagentOpenScreen:"); + #endif + + if (nxagentDoFullGeneration == 1 || + nxagentReconnectTrap == 1) + { + valuemask = CWBackPixel | CWEventMask | CWColormap | + (nxagentOption(Fullscreen) == 1 ? CWOverrideRedirect : 0); + + attributes.background_pixel = nxagentBlackPixel; + + nxagentGetDefaultEventMask((Mask*)&attributes.event_mask); + + attributes.colormap = nxagentDefaultVisualColormap(nxagentDefaultVisual(pScreen)); + + if (nxagentOption(Fullscreen) == 1) + { + attributes.override_redirect = True; + + if (nxagentReconnectTrap) + { + /* + * We need to disable the host's screensaver or + * it will otherwise grab the screen even if it + * is under agent's control. + */ + + XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking); + } + } + + /* + * This would be used when running agent + * embedded into another X window. + */ + + if (nxagentParentWindow != 0) + { + nxagentDefaultWindows[pScreen->myNum] = nxagentParentWindow; + + nxagentGetDefaultEventMask(&mask); + + XSelectInput(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], mask); + } + else + { + /* + * Create any top-level window as a child of the + * real root of the remote display. See also the + * InitRootWindow() procedure and the function + * handling the splash screen. + */ + + if (nxagentOption(Rootless) == True) + { + nxagentDefaultWindows[pScreen->myNum] = DefaultRootWindow(nxagentDisplay); + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Using root window id [%ld].\n", + nxagentDefaultWindows[pScreen->myNum]); + #endif + } + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Going to create new default window.\n"); + #endif + + nxagentDefaultWindows[pScreen->myNum] = + XCreateWindow(nxagentDisplay, + DefaultRootWindow(nxagentDisplay), + nxagentOption(X) + POSITION_OFFSET, + nxagentOption(Y) + POSITION_OFFSET, + nxagentOption(Width), + nxagentOption(Height), + nxagentOption(BorderWidth), + pScreen->rootDepth, + InputOutput, + nxagentDefaultVisual(pScreen), + valuemask, &attributes); + + if (nxagentOption(Rootless) == 0) + { + valuemask = CWEventMask; + mask = PointerMotionMask; + attributes.event_mask = mask; + + nxagentInputWindows[pScreen -> myNum] = + XCreateWindow(nxagentDisplay, + nxagentDefaultWindows[pScreen -> myNum], + 0, 0, + nxagentOption(Width), + nxagentOption(Height), + 0, 0, InputOnly, + nxagentDefaultVisual(pScreen), + valuemask , &attributes); + } + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Created new default window with id [%ld].\n", + nxagentDefaultWindows[pScreen->myNum]); + #endif + + if (nxagentOption(Fullscreen)) + { + nxagentFullscreenWindow = nxagentDefaultWindows[pScreen->myNum]; + } + + if (nxagentIpaq) + { + XWindowChanges ch; + unsigned int ch_mask; + + ch.stack_mode = Below; + ch_mask = CWStackMode; + + XConfigureWindow(nxagentDisplay, nxagentFullscreenWindow, ch_mask, &ch); + } + } + + if (nxagentOption(Fullscreen)) + { + /* + * FIXME: Do we still need to set this property? + */ + + if (nxagentAtoms[8] != 0) + { + XChangeProperty(nxagentDisplay, + nxagentDefaultWindows[pScreen->myNum], + nxagentAtoms[8], /* NX_AGENT_SIGNATURE */ + XA_STRING, + 8, + PropModeReplace, + (unsigned char*) "X-AGENT", + strlen("X-AGENT")); + } + + nxagentGetDefaultEventMask(&mask); + + XSelectInput(nxagentDisplay, nxagentFullscreenWindow, mask); + } + + sizeHints.flags = PPosition | PMinSize | PMaxSize; + sizeHints.x = nxagentOption(X) + POSITION_OFFSET; + sizeHints.y = nxagentOption(Y) + POSITION_OFFSET; + sizeHints.min_width = MIN_NXAGENT_WIDTH; + sizeHints.min_height = MIN_NXAGENT_HEIGHT; + + sizeHints.width = nxagentOption(RootWidth); + sizeHints.height = nxagentOption(RootHeight); + + if (nxagentOption(DesktopResize) == 1) + { + sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + } + else + { + sizeHints.max_width = nxagentOption(RootWidth); + sizeHints.max_height = nxagentOption(RootHeight); + } + + if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue) + sizeHints.flags |= USPosition; + if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue) + sizeHints.flags |= USSize; + + XSetStandardProperties(nxagentDisplay, + nxagentDefaultWindows[pScreen->myNum], + nxagentWindowName, + nxagentWindowName, + nxagentIconPixmap, + argv, argc, &sizeHints); + + wmHints.icon_pixmap = nxagentIconPixmap; + + if (useXpmIcon) + { + wmHints.icon_mask = nxagentIconShape; + wmHints.flags = IconPixmapHint | IconMaskHint; + } + else + { + wmHints.flags = IconPixmapHint; + } + + XSetWMHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &wmHints); + + /* + * Clear the window but let it unmapped. We'll map it + * at the time the we'll initialize our screen root + * and only if we are not running in rootless mode. + */ + + XClearWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum]); + + if (nxagentOption(Fullscreen)) + { + valuemask = CWBackPixmap | CWColormap | CWOverrideRedirect; + } + else + { + valuemask = CWBackPixmap | CWColormap; + } + + attributes.background_pixmap = nxagentScreenSaverPixmap; + attributes.colormap = DefaultColormap(nxagentDisplay, DefaultScreen(nxagentDisplay)); + + if (nxagentOption(Fullscreen)) + { + attributes.override_redirect = False; + if (nxagentReconnectTrap) + { + XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow, True, GrabModeAsync, + GrabModeAsync, CurrentTime); + } + } + + if (nxagentOption(Fullscreen)) + { + nxagentIconWindow = nxagentCreateIconWindow(); + } + else + { + nxagentIconWindow = 0; + } + + /* + * When we don't have window manager we grab keyboard + * to let nxagent get keyboard events. + */ + + if (!nxagentWMIsRunning && !nxagentOption(Fullscreen)) + { + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: No window manager, we call XGrabKeyboard.\n"); + #endif + + XGrabKeyboard(nxagentDisplay, RootWindow (nxagentDisplay, 0), True, GrabModeAsync, + GrabModeAsync, CurrentTime); + } + } + + if (!nxagentCreateDefaultColormap(pScreen)) + { + #ifdef PANIC + fprintf(stderr, "nxagentOpenScreen: Failed to create default colormap for screen.\n"); + #endif + + return False; + } + + /* + * The purpose of this check is to verify if there + * is a window manager running. Unfortunately due + * to the way we manage the intern atoms call, the + * atom will always exist. + */ + + if (nxagentWMIsRunning) + { + XlibAtom deleteWMatom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */ + + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: Found WM, delete window atom [%ld].\n", + deleteWMatom); + #endif + + if (nxagentOption(Rootless) == False) + { + /* + * Set the WM_DELETE_WINDOW protocol for the main agent + * window and, if we are in fullscreen mode, include the + * icon window. + */ + + XSetWMProtocols(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &deleteWMatom, 1); + + /* + if (nxagentOption(Fullscreen)) + { + XSetWMProtocols(nxagentDisplay, nxagentIconWindow, &deleteWMatom, 1); + } + */ + } + else + { + /* + * We need to register the ICCCM WM_DELETE_WINDOW + * protocol for any top-level window or the agent + * will be killed if any window is closed. + */ + + XSetWMProtocols(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &deleteWMatom, 1); + + #ifdef TEST + fprintf(stderr, "Warning: Not setting the WM_DELETE_WINDOW protocol.\n"); + #endif + } + } + else + { + /* + * We should always enable the configuration of the + * remote X server's devices if we are running full- + * screen and there is no WM running. + */ + + if (nxagentOption(Fullscreen)) + { + #ifdef TEST + fprintf(stderr, "nxagentOpenScreen: WARNING! Forcing propagation of device control changes.\n"); + #endif + + nxagentChangeOption(DeviceControl, True); + } + } + + /* + * Inform the user whether the agent's clients will + * be able to change the real X server's keyboard + * and pointer settings. + */ + + if (nxagentOption(DeviceControl) == False) + { + fprintf(stderr, "Info: Not using local device configuration changes.\n"); + } + else + { + fprintf(stderr, "Info: Using local device configuration changes.\n"); + } + + #ifdef RENDER + + /* + * if (nxagentRenderEnable && !nxagentReconnectTrap) + * { + * if (!nxagentPictureInit(pScreen, 0, 0)) + * { + * nxagentRenderEnable = False; + * + * return FALSE; + * } + * + * if (nxagentAlphaEnabled) + * { + * fprintf(stderr, "Info: Using alpha channel in render extension.\n"); + * } + * } + */ + + #endif /* RENDER */ + + /* + * Check if the composite extension is + * supported on the remote display and + * prepare the agent for its use. + */ + + nxagentCompositeExtensionInit(); + + + #ifdef NXAGENT_TIMESTAMP + + { + extern unsigned long startTime; + + fprintf(stderr, "Screen: open screen finished, time is [%d] milliseconds.\n", + GetTimeInMillis() - startTime); + } + + #endif + + #ifdef WATCH + + fprintf(stderr, "nxagentOpenScreen: Watchpoint 8.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#1 U 2 1 5344 bits (1 KB) -> 2344 bits (0 KB) -> 2672/1 -> 1172/1 = 2.280:1 +#16 11 2816 bits (0 KB) -> 197 bits (0 KB) -> 256/1 -> 18/1 = 14.294:1 +#91 1 16640 bits (2 KB) -> 12314 bits (2 KB) -> 16640/1 -> 12314/1 = 1.351:1 +#98 2 512 bits (0 KB) -> 57 bits (0 KB) -> 256/1 -> 28/1 = 8.982:1 +*/ + + sleep(30); + + #endif + + return True; +} + +Bool nxagentCloseScreen(int index, ScreenPtr pScreen) +{ + int i; + + for (i = 0; i < pScreen->numDepths; i++) + { + xfree(pScreen->allowedDepths[i].vids); + } + + /* + * Free the frame buffer. + */ + + xfree(((PixmapPtr)pScreen -> devPrivate) -> devPrivate.ptr); + + xfree(pScreen->allowedDepths); + xfree(pScreen->visuals); + xfree(pScreen->devPrivate); + + /* + * Reset the geometry and alpha information + * used by proxy to unpack the packed images. + */ + + nxagentResetVisualCache(); + nxagentResetAlphaCache(); + nxagentReleaseAllSplits(); + + /* + * The assumption is that all X resources will be + * destroyed upon closing the display connection. + * There is no need to generate extra protocol. + */ + + return True; +} + +Bool nxagentResizeScreen(ScreenPtr pScreen, int width, int height, + int mmWidth, int mmHeight) +{ + BoxRec box; + XSizeHints sizeHints; + PixmapPtr pPixmap; + char *fbBits; + + int oldWidth; + int oldHeight; + int oldMmWidth; + int oldMmHeight; + + WindowPtr pWin; + RegionPtr pRootWinSize; + + #ifdef TEST + nxagentPrintAgentGeometry("Before Resize Screen", "nxagentResizeScreen:"); + #endif + + /* + * Change screen properties. + */ + + oldWidth = pScreen -> width; + oldHeight = pScreen -> height; + oldMmWidth = pScreen -> mmWidth; + oldMmHeight = pScreen -> mmHeight; + + pScreen -> width = width; + pScreen -> height = height; + + /* + * Compute screen dimensions if they aren't given. + */ + + if (mmWidth == 0) + { + mmWidth = (width * 254 + monitorResolution * 5) / (monitorResolution * 10); + + if (mmWidth < 1) + { + mmWidth = 1; + } + } + + if (mmHeight == 0) + { + mmHeight = (height * 254 + monitorResolution * 5) / (monitorResolution * 10); + + if (mmHeight < 1) + { + mmHeight = 1; + } + } + + pScreen -> mmWidth = mmWidth; + pScreen -> mmHeight = mmHeight; + + pPixmap = fbGetScreenPixmap(pScreen); + + if ((fbBits = realloc(pPixmap -> devPrivate.ptr, PixmapBytePad(width, pScreen->rootDepth) * + height * BitsPerPixel(pScreen->rootDepth) / 8)) == NULL) + { + pScreen -> width = oldWidth; + pScreen -> height = oldHeight; + pScreen -> mmWidth = oldMmWidth; + pScreen -> mmHeight = oldMmHeight; + + goto nxagentResizeScreenError; + } + + if (!miModifyPixmapHeader(pPixmap, width, height, + pScreen->rootDepth, BitsPerPixel(pScreen->rootDepth), + PixmapBytePad(width, + pScreen->rootDepth), fbBits)) + { +/* +FIXME: We should try to restore the previously + reallocated frame buffer pixmap. +*/ + + pScreen -> width = oldWidth; + pScreen -> height = oldHeight; + pScreen -> mmWidth = oldMmWidth; + pScreen -> mmHeight = oldMmHeight; + + goto nxagentResizeScreenError; + } + + nxagentChangeOption(RootWidth, width); + nxagentChangeOption(RootHeight, height); + + if (nxagentOption(Fullscreen)) + { + nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + + nxagentChangeOption(RootX, (WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) + - nxagentOption(RootWidth)) / 2); + nxagentChangeOption(RootY, (HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) + - nxagentOption(RootHeight)) / 2); + } + else + { + nxagentChangeOption(RootX, 0); + nxagentChangeOption(RootY, 0); + } + + nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth)); + nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight)); + + /* + * Change agent window size and size hints. + */ + + sizeHints.flags = PPosition | PMinSize | PMaxSize; + sizeHints.x = nxagentOption(X); + sizeHints.y = nxagentOption(Y); + + sizeHints.min_width = MIN_NXAGENT_WIDTH; + sizeHints.min_height = MIN_NXAGENT_HEIGHT; + sizeHints.width = width; + sizeHints.height = height; + + if (nxagentOption(DesktopResize) == 1) + { + sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + } + else + { + sizeHints.max_width = nxagentOption(RootWidth); + sizeHints.max_height = nxagentOption(RootHeight); + } + + if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue) + { + sizeHints.flags |= USPosition; + } + + if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue) + { + sizeHints.flags |= USSize; + } + + XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &sizeHints); + + if (nxagentOption(Fullscreen)) + { + XResizeWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], + WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), + HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + + XResizeWindow(nxagentDisplay, nxagentInputWindows[pScreen -> myNum], + WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), + HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + } + else + { + XResizeWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], width, height); + + if (nxagentOption(Rootless) == 0) + { + XResizeWindow(nxagentDisplay, nxagentInputWindows[pScreen -> myNum], width, height); + } + } + + /* + * Set properties for the agent root window. + */ + + box.x1 = 0; + box.y1 = 0; + box.x2 = width; + box.y2 = height; + + WindowTable[pScreen -> myNum] -> drawable.width = width; + WindowTable[pScreen -> myNum] -> drawable.height = height; + WindowTable[pScreen -> myNum] -> drawable.x = 0; + WindowTable[pScreen -> myNum] -> drawable.y = 0; + + REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> borderSize, &box, 1); + REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> winSize, &box, 1); + REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> clipList, &box, 1); + REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> borderClip, &box, 1); + + (*pScreen -> PositionWindow)(WindowTable[pScreen -> myNum], 0, 0); + + pRootWinSize = &WindowTable[pScreen -> myNum] -> winSize; + + /* + * Force a fictitious resize of all the top + * level windows, in order to trigger the + * window tree validation. + */ + + if (nxagentOption(Rootless) == 0) + { + for (pWin = WindowTable[pScreen -> myNum] -> firstChild; pWin != NULL; pWin = pWin -> nextSib) + { + + (*pWin -> drawable.pScreen -> ResizeWindow)(pWin, pWin -> drawable.x, + pWin -> drawable.y, + pWin -> drawable.width, + pWin -> drawable.height, + pWin -> nextSib); + + } + } + + XMoveWindow(nxagentDisplay, nxagentWindow(WindowTable[0]), + nxagentOption(RootX), nxagentOption(RootY)); + + nxagentMoveViewport(pScreen, 0, 0); + + #ifdef TEST + nxagentPrintAgentGeometry("After Resize Screen", "nxagentResizeScreen:"); + #endif + + fprintf(stderr, "Info: Screen [%d] resized to geometry [%dx%d].\n", + pScreen -> myNum, width, height); + + return 1; + +nxagentResizeScreenError: + + return 0; +} + +void nxagentShadowSetRatio(float floatXRatio, float floatYRatio) +{ + int intXRatio; + int intYRatio; + + if (floatXRatio == 0) + { + floatXRatio = 1.0; + } + + if (floatYRatio == 0) + { + floatYRatio = 1.0; + } + + intXRatio = floatXRatio * (1 << PRECISION); + intYRatio = floatYRatio * (1 << PRECISION); + + nxagentChangeOption(FloatXRatio, floatXRatio); + nxagentChangeOption(FloatYRatio, floatYRatio); + + nxagentChangeOption(XRatio, intXRatio); + nxagentChangeOption(YRatio, intYRatio); + + #ifdef TEST + fprintf(stderr, "Info: Using X ratio [%f] Y ratio [%f].\n", + nxagentOption(FloatXRatio), nxagentOption(FloatYRatio)); + #endif +} + +void nxagentShadowSetWindowsSize(void) +{ + XResizeWindow(nxagentDisplay, nxagentDefaultWindows[0], + nxagentOption(Width), nxagentOption(Height)); + + XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0, + nxagentOption(Width), nxagentOption(Height)); +} + +void nxagentShadowSetWindowOptions(void) +{ + nxagentChangeOption(RootWidth, nxagentScale(nxagentShadowWidth, nxagentOption(XRatio))); + nxagentChangeOption(RootHeight, nxagentScale(nxagentShadowHeight, nxagentOption(YRatio))); + + nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth)); + nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight)); + + nxagentChangeOption(RootX, (nxagentOption(Width) - nxagentOption(RootWidth)) >> 1); + nxagentChangeOption(RootY, (nxagentOption(Height) - nxagentOption(RootHeight)) >> 1); +} + +int nxagentShadowInit(ScreenPtr pScreen, WindowPtr pWin) +{ + int i; + char *layout = NULL; + extern char *nxagentKeyboard; + XlibGC gc; + XGCValues value; + + #ifndef __CYGWIN32__ + + Atom nxagentShadowAtom; + + int fd; + + #endif + + #ifdef TEST + fprintf(stderr, "Info: Init shadow session. nxagentDisplayName [%s] nxagentDisplay " + "[%p] nxagentShadowDisplayName [%s].\n", nxagentDisplayName, + (void *) nxagentDisplay, nxagentShadowDisplayName); + #endif + + if (nxagentKeyboard != NULL) + { + for (i = 0; nxagentKeyboard[i] != '/' && nxagentKeyboard[i] != 0; i++); + + if(nxagentKeyboard[i] == 0 || nxagentKeyboard[i + 1] == 0 || i == 0) + { + #ifdef WARNING + fprintf(stderr,"Warning: Wrong keyboard type: %s.\n", nxagentKeyboard); + #endif + } + else + { + layout = malloc(strlen(&nxagentKeyboard[i + 1]) + 1); + + strcpy(layout, &nxagentKeyboard[i + 1]); + } + } + + #ifdef DEBUG + fprintf(stderr, "nxagentShadowInit: Setting the master uid [%d].\n", nxagentShadowUid); + #endif + +#if !defined (__CYGWIN32__) && !defined (WIN32) + + if (nxagentShadowUid != -1) + { + NXShadowSetDisplayUid(nxagentShadowUid); + } + + if (nxagentOption(UseDamage) == 0) + { + NXShadowDisableDamage(); + } + +#endif + + if (NXShadowCreate(nxagentDisplay, layout, nxagentShadowDisplayName, + (void *) &nxagentShadowDisplay) != 1) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowInit: Failed to initialize shadow display [%s].\n", nxagentShadowDisplayName); + #endif + + return -1; + } + + /* + * The shadow nxagent sets the _NX_SHADOW + * property on the master X server root + * window in order to notify its presence. + */ + + #ifndef __CYGWIN__ + + nxagentShadowAtom = XInternAtom(nxagentShadowDisplay, "_NX_SHADOW", False); + + XChangeProperty(nxagentShadowDisplay, DefaultRootWindow(nxagentShadowDisplay), + nxagentShadowAtom, XA_STRING, 8, PropModeReplace, NULL, 0); + #endif + + if (NXShadowAddUpdaterDisplay(nxagentDisplay, &nxagentShadowWidth, + &nxagentShadowHeight, &nxagentMasterDepth) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowInit: Failed to add display [%s].\n", + nxagentDisplayName); + #endif + + return -1; + } + + #ifndef __CYGWIN32__ + + if (nxagentOption(Fullscreen) == 1) + { + nxagentShadowSetRatio(WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 1.0 / nxagentShadowWidth, + HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 1.0 / nxagentShadowHeight); + } + else if (nxagentUserGeometry.flag != 0) + { + nxagentShadowSetRatio(nxagentOption(RootWidth) * 1.0 / nxagentShadowWidth, + nxagentOption(RootHeight) * 1.0 / nxagentShadowHeight); + } + + if (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -> class != TrueColor || + DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentShadowDisplay)) -> class != TrueColor) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowInit: PANIC! The visual class is not TrueColor.\n"); + #endif + + return -1; + } + + #endif + + nxagentShadowDepth = pScreen -> rootDepth; + + switch (nxagentMasterDepth) + { + case 32: + case 24: + { + if (nxagentShadowDepth == 16) + { + nxagentCheckDepth = 1; + } + else if (nxagentShadowDepth == 8) + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowInit: PANIC! The target depth is 8 bit.\n"); + #endif + + return -1; + } + + nxagentBppMaster = 4; + + break; + } + case 16: + { + if (nxagentShadowDepth > 16) + { + nxagentCheckDepth = 1; + } + else if (nxagentShadowDepth == 8) + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowInit: PANIC! The target depth is 8 bit.\n"); + #endif + + return -1; + } + + nxagentBppMaster = 2; + + break; + } + case 8: + { + if (nxagentShadowDepth != 8) + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowInit: PANIC! The target depth is 8 bit.\n"); + #endif + + return -1; + } + + nxagentBppMaster = 1; + + break; + } + default: + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowInit: PANIC! The depth is not 32, 24, 16 or 8 bit.\n"); + #endif + + return -1; + } + } + + if (nxagentShadowDepth >= 24) + { + nxagentBppShadow = 4; + } + else if (nxagentShadowDepth == 16) + { + nxagentBppShadow = 2; + } + else if (nxagentShadowDepth == 8) + { + nxagentBppShadow = 1; + } + +#if !defined(__CYGWIN__) + + imageByteOrder = nxagentShadowDisplay -> byte_order; + + fd = XConnectionNumber(nxagentShadowDisplay); + + nxagentShadowXConnectionNumber = fd; + +#endif + + #ifdef TEST + fprintf(stderr, "nxagentAddXConnection: Adding the X connection [%d] " + "to the device set.\n", fd); + #endif + + AddEnabledDevice(nxagentShadowXConnectionNumber); + + accessPixmapID = FakeClientID(serverClient -> index); + + AddResource(accessPixmapID, RT_PIXMAP, (pointer)nxagentShadowPixmapPtr); + + accessWindowID = FakeClientID(serverClient -> index); + + AddResource(accessWindowID, RT_WINDOW, (pointer)nxagentShadowWindowPtr); + + nxagentResizeScreen(pScreen, nxagentShadowWidth, nxagentShadowHeight, pScreen -> mmWidth, pScreen -> mmHeight); + + nxagentShadowCreateMainWindow(pScreen, pWin, nxagentShadowWidth, nxagentShadowHeight); + + nxagentShadowSetWindowsSize(); + + nxagentSetWMNormalHints(0); + + XMapWindow(nxagentDisplay, nxagentDefaultWindows[0]); + + /* + * Clean up the main window. + */ + + value.foreground = 0x00000000; + value.background = 0x00000000; + value.plane_mask = 0xffffffff; + value.fill_style = FillSolid; + + gc = XCreateGC(nxagentDisplay, nxagentPixmap(nxagentShadowPixmapPtr), GCBackground | + GCForeground | GCFillStyle | GCPlaneMask, &value); + + XFillRectangle(nxagentDisplay, nxagentPixmap(nxagentShadowPixmapPtr), gc, 0, 0, + nxagentShadowWidth, nxagentShadowHeight); + + XFreeGC(nxagentDisplay, gc); + + REGION_INIT(pScreen, &nxagentShadowUpdateRegion, (BoxRec*)NULL, 1); + + return 0; +} + +int nxagentShadowCreateMainWindow(ScreenPtr pScreen, WindowPtr pWin, int width, int height) +{ + XWindowChanges changes; + Mask mask,maskb; + XID values[4], *vlist; + int error; + XID xid; + + nxagentShadowWidth = width; + nxagentShadowHeight = height; + + NXShadowUpdateBuffer((void *)&nxagentShadowBuffer); + + #ifdef TEST + fprintf(stderr, "nxagentShadowCreateMainWindow: Update frame buffer [%p].\n", nxagentShadowBuffer); + #endif + + nxagentShadowSetWindowOptions(); + + if (nxagentShadowPixmapPtr != NULL) + { + nxagentDestroyPixmap(nxagentShadowPixmapPtr); + } + + if (nxagentShadowWindowPtr != NULL) + { + DeleteWindow(nxagentShadowWindowPtr, accessWindowID); + } + + nxagentShadowPixmapPtr = nxagentCreatePixmap(pScreen, nxagentShadowWidth, nxagentShadowHeight, nxagentShadowDepth); + + if (nxagentShadowPixmapPtr) + { + ChangeResourceValue(accessPixmapID, RT_PIXMAP, (pointer) nxagentShadowPixmapPtr); + nxagentShadowPixmapPtr -> drawable.id = accessPixmapID; + + #ifdef TEST + fprintf(stderr, "nxagentShadowCreateMainWindow: nxagentShadowPixmapPtr [%p] PixmapM -> drawable.id [%lu].\n", + (void *)nxagentShadowPixmapPtr, nxagentShadowPixmapPtr -> drawable.id); + fprintf(stderr, "nxagentShadowCreateMainWindow: Create pixmap with width [%d] height [%d] depth [%d].\n", + nxagentShadowWidth, nxagentShadowHeight, (int)nxagentShadowDepth); + #endif + } + else + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create pixmap with width [%d] height [%d] depth [%d].\n", + nxagentShadowWidth, nxagentShadowHeight, (int)nxagentShadowDepth); + #endif + } + + XFreePixmap(nxagentDisplay, nxagentPixmap(nxagentVirtualPixmap(nxagentShadowPixmapPtr))); + + xid = XCreatePixmap(nxagentDisplay, nxagentDefaultWindows[0], + nxagentScale(nxagentShadowWidth, nxagentOption(XRatio)), + nxagentScale(nxagentShadowHeight, nxagentOption(YRatio)), nxagentShadowDepth); + + nxagentPixmap(nxagentVirtualPixmap(nxagentShadowPixmapPtr)) = xid; + + nxagentPixmap(nxagentRealPixmap(nxagentShadowPixmapPtr)) = xid; + + if (nxagentShadowGCPtr != NULL) + { + FreeScratchGC(nxagentShadowGCPtr); + } +/* + * FIXME: Should use CreateGC. + */ + nxagentShadowGCPtr = GetScratchGC(nxagentShadowPixmapPtr -> drawable.depth, nxagentShadowPixmapPtr -> drawable.pScreen); + + if (nxagentShadowGCPtr) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowCreateMainWindow: Created GC with pGC[%p]\n", nxagentShadowGCPtr); + #endif + ValidateGC((DrawablePtr)nxagentShadowPixmapPtr, nxagentShadowGCPtr); + } + else + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create GC."); + #endif + } + + mask = CWBackPixmap | CWEventMask | CWCursor; + + nxagentGetDefaultEventMask(&maskb); + maskb |= ResizeRedirectMask | ExposureMask; + + vlist = values; + *vlist++ = (XID)nxagentShadowPixmapPtr -> drawable.id; + *vlist++ = (XID)maskb; + + *vlist = (XID)None; + + nxagentShadowWindowPtr = CreateWindow(accessWindowID, pWin, 0, 0, nxagentShadowWidth, + nxagentShadowHeight, 0, InputOutput, mask, (XID *)values, + nxagentShadowDepth, serverClient, CopyFromParent, &error); + + mask = CWWidth | CWHeight; + changes.width = nxagentScale(nxagentShadowWidth, nxagentOption(XRatio)); + changes.height = nxagentScale(nxagentShadowHeight, nxagentOption(YRatio)); + + XConfigureWindow(nxagentDisplay, nxagentWindow(nxagentShadowWindowPtr), mask, &changes); + + nxagentMoveViewport(pScreen, 0, 0); + + if (nxagentShadowWindowPtr && !error) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowCreateMainWindow: Create window with nxagentShadowWindowPtr [%p]" + "nxagentShadowWindowPtr -> drawable.id [%lu].\n", (void *) nxagentShadowWindowPtr, + nxagentShadowWindowPtr -> drawable.id); + + fprintf(stderr, "nxagentShadowCreateMainWindow: parent nxagentShadowWindowPtr [%p] parent -> drawable.id [%lu].\n", + (void *)nxagentShadowWindowPtr->parent, nxagentShadowWindowPtr -> parent -> drawable.id); + + #endif + + ChangeResourceValue(accessWindowID, RT_WINDOW, (pointer) nxagentShadowWindowPtr); + } + else + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create window.\n"); + #endif + } + + XMapWindow(nxagentDisplay, nxagentWindow(nxagentShadowWindowPtr)); + MapWindow(nxagentShadowWindowPtr, serverClient); + + mask = CWX | CWY | CWWidth | CWHeight; + changes.x = nxagentOption(RootX); + changes.y = nxagentOption(RootY); + changes.width = nxagentScale(nxagentShadowWidth, nxagentOption(XRatio)); + changes.height = nxagentScale(nxagentShadowHeight, nxagentOption(YRatio)); + XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), mask, &changes); + + #ifdef TEST + fprintf(stderr, "nxagentShadowCreateMainWindow: Completed mapping of Access window.\n"); + #endif + + return 0; +} + +int nxagentShadowSendUpdates(int *suspended) +{ + *suspended = 0; + + if (REGION_NIL(&nxagentShadowUpdateRegion) == 1) + { + return 0; + } + + nxagentMarkCorruptedRegion((DrawablePtr)nxagentShadowPixmapPtr, &nxagentShadowUpdateRegion); + + REGION_EMPTY(nxagentShadowPixmapPtr -> drawable.pScreen, &nxagentShadowUpdateRegion); + + return 1; +} + +int nxagentShadowPoll(PixmapPtr nxagentShadowPixmapPtr, GCPtr nxagentShadowGCPtr, + unsigned char nxagentShadowDepth, int nxagentShadowWidth, + int nxagentShadowHeight, char *nxagentShadowBuffer, int *changed, int *suspended) +{ + int x, y, y2, n, c, line; + int result; + long numRects; + unsigned int width, height, length; + char *tBuffer = NULL; + char *iBuffer, *ptBox; + BoxRec *pBox; + RegionRec updateRegion; + RegionRec tempRegion; + BoxRec box; + int overlap; + + + REGION_NULL(pScreen, &updateRegion); + + REGION_NULL(pScreen, &tempRegion); + +#ifdef __CYGWIN32__ + + if (NXShadowCaptureCursor(nxagentWindow(nxagentShadowWindowPtr), + nxagentShadowWindowPtr -> drawable.pScreen -> visuals) == -1) + { + #ifdef WARNING + fprintf(stderr, "nxagentShadowPoll: Failed to capture cursor.\n"); + #endif + } + +#endif + + result = NXShadowHasChanged(nxagentUserInput, NULL, suspended); + + *changed = result; + + if (result == 1) + { + if (nxagentWMPassed == 0) + { + nxagentRemoveSplashWindow(NULL); + } + + NXShadowExportChanges(&numRects, &ptBox); + pBox = (BoxRec *)ptBox; + + #ifdef TEST + fprintf(stderr, "nxagentShadowPoll: nRects[%ld],pBox[%p] depth[%d].\n", numRects, pBox, nxagentShadowDepth); + #endif + + for (n = 0; n < numRects; n++) + { + /* + * The BoxRec struct defined in the Xserver has a different + * variable order in comparison with the BoxRec struct in the Xlib. + * the second and third field are inverted. + */ + + x = pBox[n].x1; + y = pBox[n].x2; + y2 = pBox[n].y2; + width = pBox[n].y1 - pBox[n].x1;/* y1 = x2 */ + height = y2 - pBox[n].x2; /* x2 = y1 */ + + line = PixmapBytePad(width, nxagentMasterDepth); + + #ifdef DEBUG + fprintf(stderr, "nxagentShadowPoll: Rectangle Number[%d] - x[%d]y[%d]W[%u]H[%u].\n", n+1, x, y, width, height); + #endif + + length = nxagentImageLength(width, height, ZPixmap, 0, nxagentMasterDepth); + + if (tBuffer) + { + xfree(tBuffer); + } + + tBuffer = xalloc(length); + + if (tBuffer == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentShadowPoll: xalloc failed.\n"); + #endif + + return -1; + } + + iBuffer = tBuffer; + + for (c = 0; c + y < y2; c++) + { + memcpy(tBuffer, nxagentShadowBuffer + x * nxagentBppMaster + + (y + c) * nxagentShadowWidth * nxagentBppMaster, line); + + tBuffer += line; + + } + + tBuffer = iBuffer; + +#ifdef __CYGWIN32__ + if (nxagentBppMaster == 2) + { + NXShadowCorrectColor(length, tBuffer); + } +#else + if (nxagentCheckDepth == 1) + { + nxagentShadowAdaptDepth(width, height, line, &tBuffer); + } +#endif + + fbPutImage(nxagentVirtualDrawable((DrawablePtr)nxagentShadowPixmapPtr), nxagentShadowGCPtr, + nxagentShadowDepth, x, y, width, height, 0, ZPixmap, tBuffer); + + box.x1 = x; + box.x2 = x + width; + box.y1 = y; + box.y2 = y + height; + + REGION_INIT(pScreen, &tempRegion, &box, 1); + + REGION_APPEND(pScreen, &updateRegion, &tempRegion); + + REGION_UNINIT(pScreen, &tempRegion); + + REGION_VALIDATE(pScreen, &updateRegion, &overlap); + + REGION_UNION(pScreen, &nxagentShadowUpdateRegion, &nxagentShadowUpdateRegion, &updateRegion); + } + + if (tBuffer) + { + xfree(tBuffer); + } + + REGION_UNINIT(pScreen, &updateRegion); + } + else if (result == -1) + { + #ifdef TEST + fprintf(stderr, "nxagentShadowPoll: polling failed!\n"); + #endif + + usleep(50 * 1000); + + return -1; + } + + return 0; +} + +void nxagentShadowAdaptDepth(unsigned int width, unsigned int height, + unsigned int lineMaster, char **buffer) +{ + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned short color16 = 0; + unsigned char * icBuffer; + unsigned char * cBuffer = NULL; + unsigned char * tBuffer = (unsigned char *) *buffer; + unsigned int lineShadow; + unsigned int length; + unsigned int c; + unsigned int pad; + unsigned int color32 = 0; + unsigned long redMask; + unsigned long greenMask; + unsigned long blueMask; + Visual *pVisual; + + length = nxagentImageLength(width, height, ZPixmap, 0, nxagentShadowDepth); + + cBuffer = xalloc(length); + icBuffer = cBuffer; + + pVisual = nxagentImageVisual((DrawablePtr) nxagentShadowPixmapPtr, nxagentShadowDepth); + + if (pVisual == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentCorrectDepthShadow: WARNING! Visual not found. Using default visual.\n"); + #endif + + pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual; + } + + #ifdef TEST + fprintf(stderr, "nxagentCorrectDepthShadow: Shadow redMask [%x] greenMask[%x] blueMask[%x].\n", + pVisual -> red_mask, pVisual -> green_mask, pVisual -> blue_mask); + #endif + + redMask = nxagentShadowDisplay -> screens[0].root_visual[0].red_mask; + greenMask = nxagentShadowDisplay -> screens[0].root_visual[0].green_mask; + blueMask = nxagentShadowDisplay -> screens[0].root_visual[0].blue_mask; + + #ifdef TEST + fprintf(stderr, "nxagentCorrectDepthShadow: Master redMask [%x] greenMask[%x] blueMask[%x].\n", + redMask, greenMask, blueMask); + #endif + + switch(nxagentMasterDepth) + { + /* + * The Shadow agent has 24 bit depth. + */ + case 16: + { + pad = lineMaster - nxagentBppMaster * width; + + #ifdef TEST + fprintf(stderr, "nxagentCorrectDepthShadow: line [%d] width[%d] pad[%d].\n", lineMaster, width, pad); + #endif + + while (height > 0) + { + for (c = 0; c < width ; c++) + { + if (imageByteOrder == LSBFirst) + { + color16 = *tBuffer++; + color16 |= (*tBuffer << 8); + } + else + { + color16 = (*tBuffer++) << 8; + color16 |= *tBuffer; + } + + blue = ((short) blueMask & color16) << 3; + blue |= 0x3; + + if (greenMask == 0x7e0) + { + /* + * bit mask 5-6-5 + */ + + green = ((short) greenMask & color16) >> 3; + green |= 0x2; + + red = ((short) redMask & color16) >> 8; + red |= 0x3; + } + else + { + /* + * bit mask 5-5-5 + */ + + green = ((short) greenMask & color16) >> 2; + green |= 0x3; + + red = ((short) redMask & color16) >> 7; + red |= 0x3; + } + + tBuffer++; + + if (nxagentDisplay -> byte_order == LSBFirst) + { + *cBuffer++ = blue; + *cBuffer++ = green; + *cBuffer++ = red; + cBuffer++; + } + else + { + cBuffer++; + *cBuffer++ = red; + *cBuffer++ = green; + *cBuffer++ = blue; + } + } + tBuffer += pad; + height--; + } + break; + } + + /* + * The Shadow agent has 16 bit depth. + */ + case 24: + { + lineShadow = PixmapBytePad(width, nxagentShadowDepth); + + pad = lineShadow - nxagentBppShadow * width; + + #ifdef TEST + fprintf(stderr, "nxagentCorrectDepthShadow: line [%d] width[%d] pad[%d].\n", lineShadow, width, pad); + #endif + + while (height > 0) + { + for (c = 0; c < width; c++) + { + if (imageByteOrder == LSBFirst) + { + color32 = *tBuffer++; + color32 |= (*tBuffer++ << 8); + color32 |= (*tBuffer++ << 16); + tBuffer++; + } + else + { + tBuffer++; + color32 = (*tBuffer++ << 16); + color32 |= (*tBuffer++ << 8); + color32 |= *tBuffer++; + } + + color16 = (color32 & (pVisual -> blue_mask << 3)) >> 3; + + if (pVisual -> green_mask == 0x7e0) + { + /* + * bit mask 5-6-5 + */ + color16 |= (color32 & (pVisual -> green_mask << 5)) >> 5; + color16 |= (color32 & (pVisual -> red_mask << 8)) >> 8; + } + else + { + /* + * bit mask 5-5-5 + */ + color16 |= (color32 & (pVisual -> green_mask << 6)) >> 6; + color16 |= (color32 & (pVisual -> red_mask << 9)) >> 9; + } + + if (nxagentDisplay -> byte_order == LSBFirst) + { + *cBuffer++ = color16 & 0xff; + *cBuffer++ = (color16 & 0xff00) >> 8; + } + else + { + *cBuffer++ = (color16 & 0xff00) >> 8; + *cBuffer++ = color16 & 0xff; + } + } + cBuffer += pad; + height--; + } + break; + } + } + cBuffer = (unsigned char *) *buffer; + *buffer = (char *) icBuffer; + + if (cBuffer != NULL) + { + xfree(cBuffer); + } +} + +#ifdef NXAGENT_ARTSD + +unsigned char fromHexNibble(char c) +{ + int uc = (unsigned char)c; + + if(uc >= '0' && uc <= '9') return uc - (unsigned char)'0'; + if(uc >= 'a' && uc <= 'f') return uc + 10 - (unsigned char)'a'; + if(uc >= 'A' && uc <= 'F') return uc + 10 - (unsigned char)'A'; + + return 16; /*error*/ +} + +void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port) +{ + Window rootWin; + XlibAtom atomReturnType; + XlibAtom propAtom; + int iReturnFormat; + unsigned long ulReturnItems; + unsigned long ulReturnBytesLeft; + unsigned char *pszReturnData = NULL; + int iReturn; + + int i,in; + char tchar[] = " "; +/* +FIXME: The port information is not used at the moment and produces a + warning on recent gcc versions. Do we need such information + to run the audio forawrding? + + char *chport; + char hex[] = "0123456789abcdef"; +*/ + rootWin = DefaultRootWindow(nxagentDisplay); + propAtom = nxagentAtoms[4]; /* MCOPGLOBALS */ + + /* + * Get at most 64KB of data. + */ + + iReturn = XGetWindowProperty(nxagentDisplay, + rootWin, + propAtom, + 0, + 65536 / 4, + False, + XA_STRING, + &atomReturnType, + &iReturnFormat, + &ulReturnItems, + &ulReturnBytesLeft, + &pszReturnData); + + if (iReturn == Success && atomReturnType != None && + ulReturnItems > 0 && pszReturnData != NULL) + { + char *local_buf; + + #ifdef TEST + fprintf(stderr, "nxagentPropagateArtsdProperties: Got [%ld] elements of format [%d] with [%ld] bytes left.\n", + ulReturnItems, iReturnFormat, ulReturnBytesLeft); + #endif + + #ifdef WARNING + + if (ulReturnBytesLeft > 0) + { + fprintf(stderr, "nxagentPropagateArtsdProperties: WARNING! Could not get the whole ARTSD property data.\n"); + } + + #endif + + local_buf = (char *) xalloc(strlen((char*)pszReturnData) + 100); + + if (local_buf) + { + memset(local_buf, 0, strlen((char *) pszReturnData)); + + for (i = 0, in = 0; pszReturnData[i] != '\0'; i++) + { + local_buf[in]=pszReturnData[i]; + + if(pszReturnData[i]==':') + { + i++; + + while(pszReturnData[i]!='\n') + { + unsigned char h; + unsigned char l; + + h = fromHexNibble(pszReturnData[i]); + i++; + if(pszReturnData[i]=='\0') continue; + l = fromHexNibble(pszReturnData[i]); + i++; + + if(h >= 16 || l >= 16) continue; + + /* + * FIXME: The array tchar[] was used uninitialized. + * It's not clear to me the original purpose of the + * piece of code using it. To be removed in future + * versions. + */ + + tchar[0]=tchar[1]; + tchar[1]=tchar[2]; + tchar[2]=tchar[3]; + tchar[3] = (h << 4) + l; + tchar[4]='\0'; + + if (strncmp(tchar, "tcp:", 4) == 0) + { + local_buf[in-7]='1'; + local_buf[in-6]=strlen(port)+47; + + in++; + local_buf[in]=pszReturnData[i-2]; + in++; + local_buf[in]=pszReturnData[i-1]; + + strcat(local_buf,"6c6f63616c686f73743a"); + in+=20; + +/* +FIXME: The port information is not used at the moment and produces a + warning on recent gcc versions. Do we need such information + to run the audio forawrding? + + chport=&port[0]; + + while(*chport!='\0') + { + in++; + local_buf[in]=hex[(*chport >> 4) & 0xf]; + in++; + local_buf[in]=hex[*chport & 0xf]; + *chport++; + } +*/ + strcat(local_buf,"00"); + in+=2; + + while(pszReturnData[i]!='\n') + { + i++; + } + } + else + { + in++; + local_buf[in]=pszReturnData[i-2]; + in++; + local_buf[in]=pszReturnData[i-1]; + } + } + + in++; + local_buf[in]=pszReturnData[i]; + } + + in++; + } + + local_buf[in]=0; + + if (strlen(local_buf)) + { + mcop_local_atom = MakeAtom(mcop_atom, strlen(mcop_atom), 1); + + ChangeWindowProperty(WindowTable[pScreen->myNum], + mcop_local_atom, + XA_STRING, + iReturnFormat, PropModeReplace, + strlen(local_buf), local_buf, 1); + } + + xfree(local_buf); + } + } +} + +#endif + +Bool nxagentReconnectScreen(void *p0) +{ + CARD16 w, h; + PixmapPtr pPixmap = (PixmapPtr)nxagentDefaultScreen->devPrivate; + int flexibility; + Mask mask; + + flexibility = *(int*)p0; + +#if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_SCREEN_DEBUG) + fprintf(stderr, "nxagentReconnectScreen\n"); +#endif + + if (!nxagentOpenScreen(0, nxagentDefaultScreen, nxagentArgc, nxagentArgv)) + { + return False; + } + + nxagentPixmap(pPixmap) = XCreatePixmap(nxagentDisplay, + nxagentDefaultWindows[nxagentDefaultScreen->myNum], + pPixmap -> drawable.width, + pPixmap -> drawable.height, + pPixmap -> drawable.depth); +#ifdef NXAGENT_RECONNECT_SCREEN_DEBUG + fprintf(stderr, "nxagentReconnectScreen: recreated %p - ID %lx\n", + pPixmap, + nxagentPixmap( pPixmap )); +#endif + w = 16; + h = 16; + (*nxagentDefaultScreen->QueryBestSize)(StippleShape, &w, &h, nxagentDefaultScreen); + if (!(nxagentPixmap(nxagentDefaultScreen->PixmapPerDepth[0]) = + XCreatePixmap(nxagentDisplay, + nxagentDefaultDrawables[1], + w, + h, + 1))); + + nxagentGetDefaultEventMask(&mask); + mask |= NXAGENT_KEYBOARD_EVENT_MASK | NXAGENT_POINTER_EVENT_MASK; + nxagentSetDefaultEventMask(mask); + XSelectInput(nxagentDisplay, nxagentDefaultWindows[0], mask); + + /* + * Turn off the screen-saver and reset the + * time to the next auto-disconnection. + */ + + SaveScreens(SCREEN_SAVER_OFF, ScreenSaverActive); + + lastDeviceEventTime.milliseconds = GetTimeInMillis(); + + return True; +} + +int nxagentRRSetScreenConfig(ScreenPtr pScreen, int width, int height) +{ + rrScrPrivPtr pScrPriv; + RRScreenSizePtr pSize; + Rotation rotation; + int rate; + short oldWidth, oldHeight; + int mmWidth, mmHeight; + int oldSize; + RRScreenSizePtr oldSizes; + + pScrPriv = rrGetScrPriv(pScreen); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!pScrPriv) + { + return 1; + } + + if (!RRGetInfo (pScreen)) + { + return 1; + } + + rotation = RR_Rotate_0; + + rate = 0; + + mmWidth = (width * 254 + monitorResolution * 5) / (monitorResolution * 10); + + if (mmWidth < 1) + { + mmWidth = 1; + } + + mmHeight = (height * 254 + monitorResolution * 5) / (monitorResolution * 10); + + if (mmHeight < 1) + { + mmHeight = 1; + } + + pSize = xalloc(sizeof(RRScreenSize)); + + pSize -> width = width; + pSize -> height = height; + pSize -> mmWidth = mmWidth; + pSize -> mmHeight = mmHeight; + + /* + * call out to ddx routine to effect the change + */ + + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure. + */ + + xfree(pSize); + + return 1; + } + + /* + * TellChanged uses this privates. + */ + + oldSize = pScrPriv->size; + oldSizes = pScrPriv->pSizes; + + pScrPriv->size = 0; + pScrPriv->pSizes = pSize; + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + { + RRSendConfigNotify (pScreen); + } + + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + + ScreenRestructured (pScreen); + + /* + * Restore old privates. + */ + + pScrPriv->pSizes = oldSizes; + pScrPriv->size = oldSize; + + xfree(pSize); + + return 0; +} + +void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin) +{ + PixmapPtr pVirtualPixmap; + nxagentPrivPixmapPtr pPrivPixmap; + XlibGC gc; + XGCValues values; + DrawablePtr pDrawable; + int i; + int xSrc, ySrc, xDst, yDst, w, h; + int nRects; + int size; + BoxPtr pBox; + XRectangle *pRects; + BoxRec extents; + RegionRec cleanRegion; + + miBSWindowPtr pBackingStore = (miBSWindowPtr) pWin -> backStorage; + + pVirtualPixmap = nxagentVirtualPixmap(pPixmap); + + pPrivPixmap = nxagentPixmapPriv(pPixmap); + + pPrivPixmap -> isBackingPixmap = 1; + + fbCopyWindowProc(&pWin -> drawable, &pVirtualPixmap -> drawable, 0, REGION_RECTS(prgnSave), + REGION_NUM_RECTS(prgnSave), xorg, yorg, FALSE, FALSE, 0, 0); + + pDrawable = &pWin -> drawable; + + values.subwindow_mode = IncludeInferiors; + + gc = XCreateGC(nxagentDisplay, nxagentWindow(WindowTable[0]), GCSubwindowMode, &values); + + /* + * Initialize to the corrupted region. + * Coordinates are relative to the window. + */ + + REGION_INIT(pWin -> pScreen, &cleanRegion, NullBox, 1); + + REGION_COPY(pWin -> pScreen, &cleanRegion, nxagentCorruptedRegion((DrawablePtr) pWin)); + + /* + * Subtract the corrupted region from the saved region. + */ + + REGION_SUBTRACT(pWin -> pScreen, &pBackingStore -> SavedRegion, &pBackingStore -> SavedRegion, &cleanRegion); + + /* + * Translate the corrupted region. Coordinates + * are relative to the backing store pixmap. + */ + + REGION_TRANSLATE(pWin -> pScreen, &cleanRegion, -pBackingStore -> x, -pBackingStore -> y); + + /* + * Compute the clean region to be saved: subtract + * the corrupted region from the region to be saved. + */ + + REGION_SUBTRACT(pWin -> pScreen, &cleanRegion, prgnSave, &cleanRegion); + + nRects = REGION_NUM_RECTS(&cleanRegion); + size = nRects * sizeof(*pRects); + pRects = (XRectangle *) xalloc(size); + pBox = REGION_RECTS(&cleanRegion); + + for (i = nRects; i-- > 0;) + { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + + XSetClipRectangles(nxagentDisplay, gc, 0, 0, pRects, nRects, Unsorted); + + xfree((char *) pRects); + + extents = *REGION_EXTENTS(pWin -> pScreen, &cleanRegion); + + REGION_UNINIT(pWin -> pScreen, &cleanRegion); + + xDst = extents.x1; + yDst = extents.y1; + +/* + * Left here the wrong solution. The window could be not + * configured yet on the real X, whilst the x and y in the + * WindowRec are the new coordinates. The right solution + * is the other, as it is independent from the window + * coordinates. + * + * xSrc = xDst + xorg - pWin -> drawable.x; + * ySrc = yDst + yorg - pWin -> drawable.y; + */ + + xSrc = xDst + pBackingStore -> x; + ySrc = yDst + pBackingStore -> y; + + w = extents.x2 - extents.x1; + h = extents.y2 - extents.y1; + + XCopyArea(nxagentDisplay, nxagentWindow(pWin), nxagentPixmap(pPixmap), gc, + xSrc, ySrc, w, h, xDst, yDst); + + nxagentAddItemBSPixmapList(nxagentPixmap(pPixmap), pPixmap, pWin, + pBackingStore -> x, pBackingStore -> y); + + #ifdef TEST + fprintf(stderr,"nxagentSaveAreas: Added pixmap [%p] with id [%d] on window [%p] to BSPixmapList.\n", + pPixmap, nxagentPixmap(pPixmap), pWin); + #endif + + XFreeGC(nxagentDisplay, gc); + + return; +} + +void nxagentRestoreAreas(PixmapPtr pPixmap, RegionPtr prgnRestore, int xorg, int yorg, WindowPtr pWin) +{ + PixmapPtr pVirtualPixmap; + RegionPtr clipRegion; + XlibGC gc; + XGCValues values; + DrawablePtr pDrawable; + int i; + int xSrc, ySrc, xDst, yDst, w, h; + int nRects; + int size; + BoxPtr pBox; + XRectangle *pRects; + BoxRec extents; + miBSWindowPtr pBackingStore; + + pBackingStore = (miBSWindowPtr) pWin -> backStorage; + + pVirtualPixmap = nxagentVirtualPixmap(pPixmap); + + fbCopyWindowProc(&pVirtualPixmap -> drawable, &pWin -> drawable, 0, REGION_RECTS(prgnRestore), + REGION_NUM_RECTS(prgnRestore), -xorg, -yorg, FALSE, FALSE, 0, 0); + + pDrawable = &pVirtualPixmap -> drawable; + + values.subwindow_mode = ClipByChildren; + + gc = XCreateGC(nxagentDisplay, nxagentWindow(WindowTable[0]), GCSubwindowMode, &values); + + /* + * Translate the reference point to the origin of the window. + */ + + REGION_TRANSLATE(pWin -> drawable.pScreen, prgnRestore, + -pWin -> drawable.x - pWin -> borderWidth, + -pWin -> drawable.y - pWin -> borderWidth); + + clipRegion = prgnRestore; + + if (nxagentDrawableStatus((DrawablePtr) pPixmap) == NotSynchronized) + { + clipRegion = REGION_CREATE(pPixmap -> drawable -> pScreen, NullBox, 1); + + REGION_COPY(pPixmap -> drawable -> pScreen, clipRegion, + nxagentCorruptedRegion((DrawablePtr) pPixmap)); + + /* + * Translate the reference point to the origin of the window. + */ + + REGION_TRANSLATE(pPixmap -> drawable -> pScreen, clipRegion, + pBackingStore -> x, pBackingStore -> y); + + REGION_INTERSECT(pPixmap -> drawable -> pScreen, clipRegion, prgnRestore, clipRegion); + + /* + * Subtract the corrupted region from the saved areas. + * miBSRestoreAreas will return the exposure region. + */ + + REGION_SUBTRACT(pPixmap -> drawable -> pScreen, &pBackingStore->SavedRegion, + &pBackingStore->SavedRegion, clipRegion); + + /* + * Store the corrupted region to send expose later. + */ + + if (nxagentRemoteExposeRegion != NULL) + { + REGION_TRANSLATE(pPixmap -> drawable -> pScreen, clipRegion, pWin -> drawable.x, pWin -> drawable.y); + + REGION_UNION(pScreen, nxagentRemoteExposeRegion, nxagentRemoteExposeRegion, clipRegion); + + REGION_TRANSLATE(pPixmap -> drawable -> pScreen, clipRegion, -pWin -> drawable.x, -pWin -> drawable.y); + } + + /* + * Compute the region to be restored. + */ + + REGION_SUBTRACT(pPixmap -> drawable -> pScreen, clipRegion, prgnRestore, clipRegion); + } + + nRects = REGION_NUM_RECTS(clipRegion); + size = nRects * sizeof(*pRects); + pRects = (XRectangle *) xalloc(size); + pBox = REGION_RECTS(clipRegion); + + for (i = nRects; i-- > 0;) + { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + + XSetClipRectangles(nxagentDisplay, gc, 0, 0, pRects, nRects, Unsorted); + + xfree(pRects); + + extents = *REGION_EXTENTS(pWin -> pScreen, clipRegion); + + xDst = extents.x1; + yDst = extents.y1; + + xSrc = xDst - xorg + pWin -> drawable.x; + ySrc = yDst - yorg + pWin -> drawable.y; + + w = extents.x2 - extents.x1; + h = extents.y2 - extents.y1; + + nxagentFlushConfigureWindow(); + + XCopyArea(nxagentDisplay, nxagentPixmap(pPixmap), nxagentWindow(pWin), gc, + xSrc, ySrc, w, h, xDst, yDst); + + XFreeGC(nxagentDisplay, gc); + + if (clipRegion != NULL && clipRegion != prgnRestore) + { + REGION_DESTROY(pPixmap -> drawable -> pScreen, clipRegion); + } + + /* + * Restore the reference point to the origin of the screen. + */ + + REGION_TRANSLATE(pWin -> drawable.pScreen, prgnRestore, + pWin -> drawable.x - pWin -> borderWidth, + pWin -> drawable.y + pWin -> borderWidth); + + return; +} + +void nxagentSetWMNormalHints(int screen) +{ + XSizeHints sizeHints; + + /* + * Change agent window size and size hints. + */ + + sizeHints.flags = PPosition | PMinSize | PMaxSize; + sizeHints.x = nxagentOption(X); + sizeHints.y = nxagentOption(Y); + + sizeHints.min_width = MIN_NXAGENT_WIDTH; + sizeHints.min_height = MIN_NXAGENT_HEIGHT; + + sizeHints.width = nxagentOption(Width); + sizeHints.height = nxagentOption(Height); + + if (nxagentOption(DesktopResize) == 1) + { + sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + } + else + { + sizeHints.max_width = nxagentOption(RootWidth); + sizeHints.max_height = nxagentOption(RootHeight); + } + + if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue) + { + sizeHints.flags |= USPosition; + } + + if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue) + { + sizeHints.flags |= USSize; + } + + XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[screen], &sizeHints); +} + +void nxagentShadowAdaptToRatio(void) +{ + XSizeHints sizeHints; + ScreenPtr pScreen; + RegionRec region; + BoxRec box; + + pScreen = screenInfo.screens[0]; + + nxagentShadowSetRatio(nxagentOption(Width) * 1.0 / WindowTable[0] -> drawable.width, + nxagentOption(Height) * 1.0 / WindowTable[0] -> drawable.height); + + nxagentShadowCreateMainWindow(pScreen, WindowTable[0], nxagentShadowWidth, nxagentShadowHeight); + + sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)); + + sizeHints.flags = PMaxSize; + + XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &sizeHints); + + box.x1 = 0; + box.y1 = 0; + box.x2 = nxagentShadowPixmapPtr -> drawable.width; + box.y2 = nxagentShadowPixmapPtr -> drawable.height; + + REGION_INIT(pScreen, ®ion, &box, 1); + + nxagentMarkCorruptedRegion((DrawablePtr)nxagentShadowPixmapPtr, ®ion); + + REGION_UNINIT(pScreen, ®ion); +} + +#ifdef DUMP + +void nxagentShowPixmap(PixmapPtr pPixmap, int x, int y, int width, int height) +{ + static int init = 1; + static Display *shadow; + static Window win; + + XlibGC gc; + XGCValues value; + XImage *image; + WindowPtr pWin = WindowTable[0]; + unsigned int format; + int depth, pixmapWidth, pixmapHeight, length; + char *data; + + depth = pPixmap -> drawable.depth; + pixmapWidth = pPixmap -> drawable.width; + pixmapHeight = pPixmap -> drawable.height; + format = (depth == 1) ? XYPixmap : ZPixmap; + + if (init) + { + shadow = XOpenDisplay("localhost:0"); + + if (shadow == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentShowPixmap: WARNING! Shadow display not opened.\n"); + #endif + + return; + } + + init = False; + } + + if (win == 0) + { + win = XCreateSimpleWindow(shadow, DefaultRootWindow(shadow), 0, 0, + width, height, 0, 0xFFCC33, 0xFF); + + XSelectInput(shadow, win, StructureNotifyMask); + + XMapWindow(shadow, win); + + for(;;) + { + XEvent e; + + XNextEvent(shadow, &e); + + if (e.type == MapNotify) + { + break; + } + } + } + else + { + XResizeWindow(nxagentDisplay, win, width, height); + XRaiseWindow(nxagentDisplay, win); + } + + length = nxagentImageLength(width, height, format, 0, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentShowPixmap: xalloc failed.\n"); + #endif + + return; + } + +/* +FIXME + image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), x, y, + width, height, AllPlanes, format); +*/ + + image = XGetImage(nxagentDisplay, RootWindow(nxagentDisplay, 0), 0, 0, + width, height, AllPlanes, format); + + if (image == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentShowPixmap: XGetImage failed.\n"); + #endif + + if (data) + { + xfree(data); + } + + return; + } + + fbGetImage((DrawablePtr)pPixmap, 0, 0, + width, height, format, AllPlanes, data); + + memcpy(image -> data, data, length); + + value.foreground = 0xffffff; + value.background = 0x000000; + value.plane_mask = 0xffffff; + value.fill_style = FillSolid; + + gc = XCreateGC(shadow, win, GCBackground | + GCForeground | GCFillStyle | GCPlaneMask, &value); + + XSync(shadow, 0); + + NXCleanImage(image); + + XPutImage(shadow, win, gc, image, 0, 0, 0, 0, width, height); + + XFlush(shadow); + + XFreeGC(shadow, gc); + + if (image != NULL) + { + XDestroyImage(image); + } + + if (data != NULL) + { + xfree(data); + } + +/* +FIXME + if (win != NULL) + { + XDestroyWindow(shadow, win); + } +*/ +} + +void nxagentFbRestoreArea(PixmapPtr pPixmap, WindowPtr pWin, int xSrc, int ySrc, int width, + int height, int xDst, int yDst) +{ + Display *shadow; + + XlibGC gc; + XGCValues value; + XImage *image; + unsigned int format; + int depth, pixmapWidth, pixmapHeight, length; + char *data = NULL; + Visual *pVisual; + + depth = pPixmap -> drawable.depth; + pixmapWidth = pPixmap -> drawable.width; + pixmapHeight = pPixmap -> drawable.height; + format = (depth == 1) ? XYPixmap : ZPixmap; + + shadow = nxagentDisplay; + + length = nxagentImageLength(width, height, format, 0, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbRestoreArea: xalloc failed.\n"); + #endif + + return; + } +/* + image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), xSrc, ySrc, + width, height, AllPlanes, format); +*/ + + if (image == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbRestoreArea: XGetImage failed.\n"); + #endif + + if (data) + { + xfree(data); + } + + return; + } + + fbGetImage((DrawablePtr)pPixmap, xSrc, ySrc, + width, height, format, AllPlanes, data); + +/* +FIXME +*/ + pVisual = nxagentImageVisual((DrawablePtr) pPixmap, depth); + + if (pVisual == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentFbRestoreArea: WARNING! Visual not found. Using default visual.\n"); + #endif + + pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual; + } + + image = XCreateImage(nxagentDisplay, pVisual, + depth, format, 0, (char *) data, + width, height, BitmapPad(nxagentDisplay), + nxagentImagePad(width, format, 0, depth)); +/* +FIXME + memcpy(image -> data, data, length); +*/ + + fprintf(stderr, "nxagentFbRestoreArea: Cleaning %d bytes of image.\n", length); + + value.foreground = 0xffffff; + value.background = 0x000000; + value.plane_mask = 0xffffff; + value.fill_style = FillSolid; + value.function = GXcopy; + + gc = XCreateGC(shadow, nxagentWindow(WindowTable[0]), GCBackground | + GCForeground | GCFillStyle | GCPlaneMask | GCFunction, &value); + + NXCleanImage(image); + + XPutImage(shadow, nxagentWindow(pWin), gc, image, 0, 0, xDst, yDst, width, height); + +/* +FIXME +*/ + XFlush(shadow); + + XFreeGC(shadow, gc); + + if (image) + { + XDestroyImage(image); + } + +/* +FIXME + if (data) + { + xfree(data); + } +*/ +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.h b/nx-X11/programs/Xserver/hw/nxagent/Screen.h new file mode 100644 index 000000000..3550dd553 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.h @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Screen_H__ +#define __Screen_H__ + +#define MIN_NXAGENT_WIDTH 80 +#define MIN_NXAGENT_HEIGHT 60 +#define NXAGENT_FRAME_WIDTH 2000 + +extern int nxagentClients; + +extern int nxagentAutoDisconnectTimeout; + +extern ScreenPtr nxagentDefaultScreen; + +extern Pixmap nxagentPixmapLogo; + +extern Window nxagentIconWindow; +extern Window nxagentFullscreenWindow; + +extern RegionRec nxagentShadowUpdateRegion; + +extern WindowPtr nxagentShadowWindowPtr; + +extern int nxagentShadowResize; + +extern short nxagentShadowUid; + +void nxagentSetScreenInfo(ScreenInfo *screenInfo); +void nxagentSetPixmapFormats(ScreenInfo *screenInfo); + +extern Window nxagentDefaultWindows[MAXSCREENS]; +extern Window nxagentInputWindows[MAXSCREENS]; +extern Window nxagentScreenSaverWindows[MAXSCREENS]; + +#ifdef VIEWPORT_FRAME + +void nxagentInitViewportFrame(ScreenPtr pScreen, WindowPtr pRootWin); + +#else /* #ifdef VIEWPORT_FRAME */ + +#define nxagentInitViewportFrame(pScreen, pRootWin) + +#endif /* #ifdef VIEWPORT_FRAME */ + +Bool nxagentOpenScreen(int index, ScreenPtr pScreen, + int argc, char *argv[]); + +Bool nxagentCloseScreen(int index, ScreenPtr pScreen); + +#define nxagentScreen(window) nxagentDefaultScreen + +extern int nxagentBitsPerPixel(int depth); + +void nxagentSetScreenSaverTime(void); + +void nxagentMinimizeFromFullScreen(ScreenPtr pScreen); +void nxagentMaximizeToFullScreen(ScreenPtr pScreen); + +Window nxagentCreateIconWindow(void); + +Bool nxagentMagicPixelZone(int x, int y); + +Bool nxagentResizeScreen(ScreenPtr pScreen, int width, int height, + int mmWidth, int mmHeight); + +int nxagentRRSetScreenConfig(ScreenPtr pScreen, int width, int height); + +extern Bool nxagentReconnectScreen(void *p0); + +void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin); + +void nxagentRestoreAreas(PixmapPtr pPixmap, RegionPtr prgnRestore, int xorg, int yorg, WindowPtr pWin); + +extern int monitorResolution; + +int nxagentShadowCreateMainWindow( ScreenPtr pScreen, WindowPtr pWin,int width, int height); + +int nxagentShadowSendUpdates(int *); + +int nxagentShadowPoll(PixmapPtr, GCPtr, unsigned char, int, int, char *, int *, int *); + +void nxagentShadowSetWindowsSize(void); + +void nxagentSetWMNormalHints(int); + +void nxagentShadowSetRatio(float, float); + +/* + * Change window settings to adapt to a ratio. + */ + +extern void nxagentShadowAdaptToRatio(void); + +/* + * The pixmap shadowing the real frame buffer. + */ + +extern PixmapPtr nxagentShadowPixmapPtr; + +#endif /* __Screen_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Splash.c b/nx-X11/programs/Xserver/hw/nxagent/Splash.c new file mode 100644 index 000000000..8de74b85b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Splash.c @@ -0,0 +1,335 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "windowstr.h" +#include "scrnintstr.h" + +#ifdef _XSERVER64 + +#include "Agent.h" + +#define GC XlibGC + +#endif /* _XSERVER64 */ + +#include "Xlib.h" +#include "Xutil.h" + +#include "Display.h" +#include "Splash.h" +#include "Screen.h" +#include "Windows.h" +#include "Atoms.h" +#include "Trap.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Colors used to paint the splash screen. + */ + +int nxagentLogoDepth; +int nxagentLogoWhite; +int nxagentLogoRed; +int nxagentLogoBlack; + +void nxagentPaintLogo(Window win, GC gc, int scale, int width, int height); + +/* + * From Screen.c. + */ + +extern Atom nxagentWMStart; + +/* + * From Clipboard.c. + */ + +extern Atom serverCutProperty; + +int nxagentShowSplashWindow(Window parentWindow) +{ + XWindowAttributes getAttributes; + XWindowChanges values; + XSetWindowAttributes attributes; + GC gc; + + #ifdef TEST + fprintf(stderr, "nxagentShowSplash: Got called.\n"); + #endif + + #ifdef NXAGENT_TIMESTAMP + { + extern unsigned long startTime; + + fprintf(stderr, "nxagentShowSplash: Initializing splash start at [%d] milliseconds.\n", + GetTimeInMillis() - startTime); + } + #endif + + XSetSelectionOwner(nxagentDisplay, nxagentWMStart, None, CurrentTime); + + nxagentWMPassed = False; + + /* + * This would cause a GetWindowAttributes and a + * GetGeometry (asynchronous) reply. We use instead + * the geometry requested by the user for the agent + * window. + * + * XGetWindowAttributes(nxagentDisplay, parentWindow, &getAttributes); + */ + + /* + * During reconnection we draw the splash over + * the default window and not over the root + * window because it would be hidden by other + * windows. + */ + + if (nxagentReconnectTrap) + { + getAttributes.x = nxagentOption(RootX); + getAttributes.y = nxagentOption(RootY); + } + else + { + getAttributes.x = 0; + getAttributes.y = 0; + } + + getAttributes.width = nxagentOption(RootWidth); + getAttributes.height = nxagentOption(RootHeight); + + #ifdef TEST + fprintf(stderr, "nxagentShowSplash: Going to create new splash window.\n"); + #endif + + nxagentSplashWindow = + XCreateSimpleWindow(nxagentDisplay, + parentWindow, + getAttributes.x, getAttributes.y, + getAttributes.width, getAttributes.height, + 0, + WhitePixel (nxagentDisplay, 0), + BlackPixel (nxagentDisplay, 0)); + + #ifdef TEST + fprintf(stderr, "nxagentShowSplash: Created new splash window with id [%ld].\n", + nxagentSplashWindow); + #endif + + gc = XCreateGC(nxagentDisplay, nxagentSplashWindow, 0, NULL); + nxagentPaintLogo(nxagentSplashWindow, gc, 1, getAttributes.width, getAttributes.height); + XMapRaised (nxagentDisplay, nxagentSplashWindow); + values.stack_mode = Above; + XConfigureWindow(nxagentDisplay, nxagentSplashWindow, CWStackMode, &values); + attributes.override_redirect = True; + XChangeWindowAttributes(nxagentDisplay, nxagentSplashWindow, CWOverrideRedirect, &attributes); + XFreeGC(nxagentDisplay, gc); + + #ifdef NXAGENT_TIMESTAMP + { + extern unsigned long startTime; + fprintf(stderr, "nxagentShowSplash: Splash ends [%d] milliseconds.\n", + GetTimeInMillis() - startTime); + } + #endif + + return True; +} + +void nxagentPaintLogo(Window win, GC gc, int scale, int width, int height) +{ + XPoint rect[4]; + XPoint m[12]; + int w, h, c, w2, h2; + + #ifdef DEBUG + fprintf(stderr, "nxagenShowtLogo: Got called.\n"); + #endif + + #ifdef NXAGENT_LOGO_DEBUG + fprintf(stderr, "nxagentPaintLogo: begin\n"); + fprintf(stderr, "nxagentPaintLogo: gen params are: w=%d h=%d d=%d r=%x w=%x b=%x\n",width, height, + nxagentLogoDepth, nxagentLogoRed, + nxagentLogoWhite, nxagentLogoBlack); + #endif + + w = width/scale; + h = height/scale; + + w2 = w/2; + h2 = h/2; + + if (height > width) + { + c = w/30; + } + else + { + c = w/48; + } + + rect[0].x = 0; rect[0].y = 0; + rect[1].x = 0; rect[1].y = h; + rect[2].x = w; rect[2].y = h; + rect[3].x = w; rect[3].y = 0; + + XSetFunction(nxagentDisplay, gc, GXcopy); + XSetFillStyle(nxagentDisplay, gc, FillSolid); + XSetForeground(nxagentDisplay, gc, nxagentLogoBlack); + XSetBackground(nxagentDisplay, gc, nxagentLogoRed); + + nxagentPixmapLogo = XCreatePixmap(nxagentDisplay, win, width, height, nxagentLogoDepth); + + if (!nxagentPixmapLogo) + { + return; + } + + XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin); + + #ifdef NXAGENT_LOGO_DEBUG + fprintf(stderr, "filled first poly\n"); + #endif + + XSetForeground(nxagentDisplay, gc, nxagentLogoRed); + XSetBackground(nxagentDisplay, gc, nxagentLogoWhite); + + rect[0].x = w2-10*c; rect[0].y = h2-8*c; + rect[1].x = w2-10*c; rect[1].y = h2+8*c; + rect[2].x = w2+10*c; rect[2].y = h2+8*c; + rect[3].x = w2+10*c; rect[3].y = h2-8*c; + + XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin); + + #ifdef NXAGENT_LOGO_DEBUG + fprintf(stderr, "filled red rect\n"); + #endif + + rect[0].x = w2-9*c; rect[0].y = h2-7*c; + rect[1].x = w2-9*c; rect[1].y = h2+7*c; + rect[2].x = w2+9*c; rect[2].y = h2+7*c; + rect[3].x = w2+9*c; rect[3].y = h2-7*c; + + XSetForeground(nxagentDisplay, gc, nxagentLogoWhite); + XSetBackground(nxagentDisplay, gc, nxagentLogoRed); + + XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin); + + /* + * Begin 'M'. + */ + + m[0].x = w2-3*c; m[0].y = h2-5*c; + m[1].x = w2+7*c; m[1].y = h2-5*c; + m[2].x = w2+7*c; m[2].y = h2+5*c; + m[3].x = w2+5*c; m[3].y = h2+5*c; + m[4].x = w2+5*c; m[4].y = h2-3*c; + m[5].x = w2+3*c; m[5].y = h2-3*c; + m[6].x = w2+3*c; m[6].y = h2+5*c; + m[7].x = w2+1*c; m[7].y = h2+5*c; + m[8].x = w2+1*c; m[8].y = h2-3*c; + m[9].x = w2-1*c; m[9].y = h2-3*c; + m[10].x = w2-1*c; m[10].y = h2+5*c; + m[11].x = w2-3*c; m[11].y = h2+5*c; + + XSetForeground(nxagentDisplay, gc, nxagentLogoRed); + XSetBackground(nxagentDisplay, gc, nxagentLogoWhite); + + XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, m, 12, Nonconvex, CoordModeOrigin); + + /* + * End 'M'. + */ + + /* + * Begin '!'. + */ + + rect[0].x = w2-7*c; rect[0].y = h2-5*c; + rect[1].x = w2-5*c; rect[1].y = h2-5*c; + rect[2].x = w2-5*c; rect[2].y = h2+2*c; + rect[3].x = w2-7*c; rect[3].y = h2+2*c; + + XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin); + + rect[0].x = w2-7*c; rect[0].y = h2+3*c; + rect[1].x = w2-5*c; rect[1].y = h2+3*c; + rect[2].x = w2-5*c; rect[2].y = h2+5*c; + rect[3].x = w2-7*c; rect[3].y = h2+5*c; + + XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin); + + /* + * End 'M'. + */ + + XSetWindowBackgroundPixmap(nxagentDisplay, win, nxagentPixmapLogo); + + #ifdef NXAGENT_LOGO_DEBUG + fprintf(stderr, "nxagentPaintLogo: end\n"); + #endif +} + +void nxagentRemoveSplashWindow(WindowPtr pWin) +{ + if (nxagentReconnectTrap) return; + + #ifdef TEST + fprintf(stderr, "nxagentRemoveSplashWindow: Destroying the splash window.\n"); + #endif + + if (!nxagentWMPassed) + { + XSetSelectionOwner(nxagentDisplay, nxagentWMStart, + nxagentDefaultWindows[0], CurrentTime); + + nxagentWMPassed = True; + } + + if (nxagentSplashWindow != None) + { + XDestroyWindow(nxagentDisplay, nxagentSplashWindow); + + nxagentSplashWindow = None; + nxagentRefreshWindows(WindowTable[0]); + + #ifdef TEST + fprintf(stderr, "nxagentRemoveSplashWindow: setting the ownership of %s (%d) on window 0x%lx\n", + "NX_CUT_BUFFER_SERVER", (int)serverCutProperty, nxagentWindow(WindowTable[0])); + #endif + + XSetSelectionOwner(nxagentDisplay, serverCutProperty, + nxagentWindow(WindowTable[0]), CurrentTime); + } + + if (nxagentPixmapLogo) + { + XFreePixmap(nxagentDisplay, nxagentPixmapLogo); + + nxagentPixmapLogo = (Pixmap) 0; + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Splash.h b/nx-X11/programs/Xserver/hw/nxagent/Splash.h new file mode 100644 index 000000000..bcc3a90b1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Splash.h @@ -0,0 +1,45 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Splash_H__ +#define __Splash_H__ + +#include "Windows.h" +#include "X11/Xdmcp.h" +#include "NXalert.h" + +#define XDM_TIMEOUT 20000 + +extern xdmcp_states XdmcpState; +extern int XdmcpTimeOutRtx; +extern int XdmcpStartTime; +extern int nxagentXdmcpUp; + +extern int nxagentLogoDepth; +extern int nxagentLogoWhite; +extern int nxagentLogoRed; +extern int nxagentLogoBlack; + +extern Window nxagentSplashWindow; + +extern int nxagentWMPassed; + +extern int nxagentShowSplashWindow(Window); + +extern void nxagentRemoveSplashWindow(WindowPtr pWin); + +#endif /* __Splash_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Split.c b/nx-X11/programs/Xserver/hw/nxagent/Split.c new file mode 100644 index 000000000..8f1c65eba --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Split.c @@ -0,0 +1,1248 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "gcstruct.h" + +#include "Agent.h" +#include "Display.h" +#include "Drawable.h" +#include "Events.h" +#include "GCs.h" + +#include "NXlib.h" + + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * This should be a macro but for now + * we make it a real function to log + * a warning in the logs. + */ + +DrawablePtr nxagentSplitDrawable(DrawablePtr pDrawable) +{ + if (pDrawable -> type == DRAWABLE_PIXMAP && + nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "nxagentSplitDrawable: WARNING! The drawable at [%p] is " + "virtual. Assuming real at [%p].\n", (void *) pDrawable, + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + return (DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable); + } + else + { + return pDrawable; + } +} + +void nxagentInitSplitResources() +{ + int resource; + + #ifdef TEST + fprintf(stderr, "nxagentInitSplitResources: Initializing the split resources.\n"); + #endif + + for (resource = 0; resource < NXNumberOfResources; resource++) + { + SplitResourcePtr pResource = &nxagentSplitResources[resource]; + + pResource -> pending = 0; + pResource -> commit = 0; + pResource -> split = NXNoResource; + pResource -> unpack = NXNoResource; + pResource -> drawable = NULL; + pResource -> region = NullRegion; + pResource -> gc = NULL; + } +} + +SplitResourcePtr nxagentAllocSplitResource() +{ + int resource; + + SplitResourcePtr pResource; + + for (;;) + { + resource = NXAllocSplit(nxagentDisplay, NXAnyResource); + + if (resource != NXNoResource) + { + #ifdef TEST + fprintf(stderr, "nxagentAllocSplitResource: Reserving resource [%d] for the next split.\n", + resource); + #endif + + break; + } + else + { + #ifdef PANIC + fprintf(stderr, "nxagentAllocSplitResource: PANIC! No more resources for the next split.\n"); + #endif +/* +FIXME: Must deal with the case all resources are exausted. +*/ + FatalError("nxagentAllocSplitResource: PANIC! No more resources for the next split.\n"); + } + } + + pResource = &nxagentSplitResources[resource]; + + if (pResource -> pending != 0 || pResource -> split != NXNoResource || + pResource -> unpack != NXNoResource || pResource -> drawable != NULL || + pResource -> region != NullRegion || pResource -> commit != 0 || + pResource -> gc != NULL) + { + /* + * This is really an unrecoverable error. + */ + + #ifdef PANIC + fprintf(stderr, "nxagentAllocSplitResource: PANIC! Invalid record for resource [%d] with " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + resource, pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + #endif + + FatalError("nxagentAllocSplitResource: PANIC! Invalid record for resource [%d] with " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + resource, pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + } + + pResource -> pending = 1; + pResource -> split = resource; + + return pResource; +} + +void nxagentFreeSplitResource(SplitResourcePtr pResource) +{ + if (pResource -> pending == 0 || pResource -> split == NXNoResource || + pResource -> drawable != NULL || pResource -> region != NullRegion || + pResource -> gc != NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentFreeSplitResource: PANIC! Invalid record provided with values " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + #endif + + FatalError("nxagentFreeSplitResource: PANIC! Invalid record provided with values " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + } + + #ifdef TEST + fprintf(stderr, "nxagentFreeSplitResource: Clearing the record for resource [%d].\n", + pResource -> split); + #endif + + NXFreeSplit(nxagentDisplay, pResource -> split); + + pResource -> pending = 0; + pResource -> commit = 0; + pResource -> split = NXNoResource; + pResource -> unpack = NXNoResource; + pResource -> drawable = NULL; + pResource -> region = NullRegion; + pResource -> gc = NULL; +} + +void nxagentInitUnpackResources() +{ +/* +FIXME: This must be implemented. +*/ +} + +UnpackResourcePtr nxagentAllocUnpackResource() +{ +/* +FIXME: This must be implemented. +*/ + return NULL; +} + +void nxagentFreeUnpackResource(UnpackResourcePtr pResource) +{ +/* +FIXME: This must be implemented. +*/ +} + +void nxagentReleaseAllSplits(void) +{ + int resource; + + #ifdef TEST + fprintf(stderr, "nxagentReleaseAllSplits: Going to release all the split resources.\n"); + #endif + + for (resource = 0; resource < NXNumberOfResources; resource++) + { + SplitResourcePtr pResource = &nxagentSplitResources[resource]; + + if (pResource != NULL && pResource -> pending == 1) + { + DrawablePtr pDrawable = pResource -> drawable; + + if (pDrawable != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentReleaseAllSplits: Releasing the drawable at [%p] for " + "resource [%d].\n", (void *) pDrawable, pResource -> split); + #endif + + nxagentReleaseSplit(pDrawable); + } + + #ifdef TEST + fprintf(stderr, "nxagentReleaseAllSplits: Freeing the resource [%d].\n", + resource); + #endif + + nxagentFreeSplitResource(pResource); + } + } +} + +/* + * Check the coherency of the split record. + */ + +#ifdef TEST + +static void nxagentCheckSplit(DrawablePtr pDrawable, SplitResourcePtr pResource) +{ + if (pResource == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentCheckSplit: PANIC! No record associated to drawable at [%p].\n", + (void *) pDrawable); + #endif + + FatalError("nxagentCheckSplit: PANIC! No record associated to drawable at [%p].\n", + (void *) pDrawable); + } + else if (pResource -> drawable != pDrawable || + pResource -> split == NXNoResource) + { + #ifdef PANIC + fprintf(stderr, "nxagentCheckSplit: PANIC! The record [%d] doesn't match the drawable at [%p].\n", + pResource -> split, (void *) pDrawable); + #endif + + FatalError("nxagentCheckSplit: PANIC! The record [%d] doesn't match the drawable at [%p].\n", + pResource -> split, (void *) pDrawable); + } + else if (pResource -> commit == 1 && + pResource -> gc == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentCheckSplit: PANIC! The record [%d] doesn't have a valid GC.\n", + pResource -> split); + #endif + + FatalError("nxagentCheckSplit: PANIC! The record [%d] doesn't have a valid GC.\n", + pResource -> split); + } +} + +static void nxagentCheckResource(SplitResourcePtr pResource, int resource) +{ + if (pResource == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentCheckResource: PANIC! No record associated to resource [%d].\n", + resource); + #endif + + FatalError("nxagentCheckResource: PANIC! No record associated to resource [%d].\n", + resource); + } + else if ((pResource -> split != resource || pResource -> pending != 1) || + (pResource -> commit == 1 && (pResource -> drawable == NULL || + pResource -> gc == NULL))) + { + #ifdef PANIC + fprintf(stderr, "nxagentCheckResource: PANIC! Invalid record for resource [%d] with " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + resource, pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + #endif + + FatalError("nxagentCheckResource: PANIC! Invalid record for resource [%d] with " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + resource, pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + } +} + +#endif + +int nxagentCreateSplit(DrawablePtr pDrawable, GCPtr *pGC) +{ + SplitResourcePtr pResource; + + pDrawable = nxagentSplitDrawable(pDrawable); + + pResource = nxagentAllocSplitResource(); + + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapPriv((PixmapPtr) pDrawable) -> splitResource = pResource; + } + else + { + nxagentWindowPriv((WindowPtr) pDrawable) -> splitResource = pResource; + } + + pResource -> drawable = pDrawable; + pResource -> commit = 1; + + /* + * Make a copy of the GC so the client + * can safely remove it. + */ + + pResource -> gc = CreateScratchGC(pDrawable -> pScreen, pDrawable -> depth); + +/* +FIXME: What do we do here? +*/ + if (pResource -> gc == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentCreateSplit: PANIC! Failed to create split GC for resource [%d].\n", + pResource -> split); + #endif + + FatalError("nxagentCreateSplit: PANIC! Failed to create split GC for resource [%d].\n", + pResource -> split); + } + else if (CopyGC(*pGC, pResource -> gc, GCFunction | GCPlaneMask | + GCSubwindowMode | GCClipXOrigin | GCClipYOrigin | + GCClipMask | GCForeground | GCBackground) != Success) + { +/* +FIXME: What do we do here? +*/ + #ifdef PANIC + fprintf(stderr, "nxagentCreateSplit: PANIC! Failed to copy split GC for resource [%d].\n", + pResource -> split); + #endif + + FatalError("nxagentCreateSplit: PANIC! Failed to copy split GC for resource [%d].\n", + pResource -> split); + } + + #ifdef TEST + fprintf(stderr, "nxagentCreateSplit: Associated GC at [%p] to resource [%d] " + "with id [%lu].\n", (void *) pResource -> gc, pResource -> split, + (unsigned long) nxagentGC(pResource -> gc)); + #endif + + *pGC = pResource -> gc; + + #ifdef TEST + fprintf(stderr, "nxagentCreateSplit: Associated resource [%d] to drawable at [%p].\n", + pResource -> split, (void *) pResource -> drawable); + #endif + + return pResource -> split; +} + +/* + * Set the region to be the current + * streaming region. + */ + +void nxagentRegionSplit(DrawablePtr pDrawable, RegionPtr pRegion) +{ + SplitResourcePtr pResource; + + pDrawable = nxagentSplitDrawable(pDrawable); + + pResource = nxagentSplitResource(pDrawable); + + #ifdef TEST + + fprintf(stderr, "nxagentRegionSplit: Associating region to resource [%d] drawable at [%p].\n", + pResource -> split, (void *) pDrawable); + + nxagentCheckSplit(pDrawable, pResource); + + #endif + + if (pResource == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentRegionSplit: PANIC! No valid split record for drawable at [%p].\n", + (void *) pDrawable); + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentRegionSplit: Associated region [%d,%d,%d,%d] to drawable at [%p] " + "with resource [%d].\n", pRegion -> extents.x1, pRegion -> extents.y1, + pRegion -> extents.x2, pRegion -> extents.y2, (void *) pDrawable, + pResource -> split); + #endif + + pResource -> region = pRegion; +} + +/* + * Remove the association between the drawable + * and the split resource. The resource is not + * deallocated until the end of the split. + */ + +void nxagentReleaseSplit(DrawablePtr pDrawable) +{ + SplitResourcePtr pResource; + + pDrawable = nxagentSplitDrawable(pDrawable); + + pResource = nxagentSplitResource(pDrawable); + + if (pResource == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentReleaseSplit: No split resources for drawable at [%p].\n", + (void *) pDrawable); + #endif + + return; + } + + #ifdef TEST + + fprintf(stderr, "nxagentReleaseSplit: Going to release resource [%d] for drawable at [%p].\n", + pResource -> split, (void *) pDrawable); + + nxagentCheckSplit(pDrawable, pResource); + + #endif + + if (pResource -> region != NullRegion) + { + /* + * If we have a region the commits + * had to be still valid. In this + * case tell the proxy to abort the + * data transfer. + */ + + #ifdef TEST + + if (pResource -> commit == 0) + { + #ifdef PANIC + fprintf(stderr, "nxagentReleaseSplit: PANIC! Found a region for resource [%d] but the " + "commits are invalid.\n", pResource -> split); + #endif + + FatalError("nxagentCheckSplit: PANIC! Found a region for resource [%d] but the " + "commits are invalid.\n", pResource -> split); + } + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentValidateSplit: Aborting the data transfer for resource [%d].\n", + pResource -> split); + #endif + + NXAbortSplit(nxagentDisplay, pResource -> split); + + #ifdef TEST + fprintf(stderr, "nxagentReleaseSplit: Freeing the region for drawable at [%p].\n", + (void *) pDrawable); + #endif + + REGION_DESTROY(pDrawable -> pScreen, pResource -> region); + + pResource -> region = NullRegion; + } + + if (pResource -> gc != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentReleaseSplit: Freeing the split GC for drawable at [%p].\n", + (void *) pDrawable); + #endif + + FreeScratchGC(pResource -> gc); + + pResource -> gc = NULL; + } + + /* + * Remove the association between the + * drawable and the resource record. + */ + + #ifdef TEST + fprintf(stderr, "nxagentReleaseSplit: Removing association to drawable at [%p].\n", + (void *) pDrawable); + #endif + + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentPixmapPriv((PixmapPtr) pDrawable) -> splitResource = NULL; + } + else + { + nxagentWindowPriv((WindowPtr) pDrawable) -> splitResource = NULL; + } + + /* + * Invalidate the commits and remove the + * association between the resource and + * the drawable. + */ + + pResource -> drawable = NULL; + pResource -> commit = 0; +} + +void nxagentValidateSplit(DrawablePtr pDrawable, RegionPtr pRegion) +{ + SplitResourcePtr pResource; + + pDrawable = nxagentSplitDrawable(pDrawable); + + pResource = nxagentSplitResource(pDrawable); + + if (pResource == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentValidateSplit: No split resource for drawable at [%p].\n", + (void *) pDrawable); + #endif + + return; + } + else if (pResource -> region == NullRegion) + { + #ifdef TEST + fprintf(stderr, "nxagentValidateSplit: No split region yet for drawable at [%p].\n", + (void *) pDrawable); + #endif + + return; + } + else if (pResource -> commit == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentValidateSplit: WARNING! Split for drawable at [%p] was " + "already invalidated.\n", (void *) pDrawable); + #endif + + return; + } + + #ifdef TEST + + fprintf(stderr, "nxagentValidateSplit: Going to validate resource [%d] drawable at [%p].\n", + pResource -> split, (void *) pDrawable); + + nxagentCheckSplit(pDrawable, pResource); + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentValidateSplit: Checking the region for resource [%d] " + "and drawable at [%p].\n", pResource -> split, (void *) pDrawable); + #endif + + /* + * If a null region is passed as parameter, + * we assume that all the commits have to + * be discarded. + */ + + if (pRegion == NullRegion) + { + #ifdef TEST + fprintf(stderr, "nxagentValidateSplit: Forcing all commits as invalid for " + "drawable at [%p].\n", (void *) pDrawable); + #endif + + nxagentReleaseSplit(pDrawable); + } + else + { + RegionRec tmpRegion; + + /* + * Check if the provided region overlaps + * the area covered by the image being + * streamed. + */ + + REGION_INIT(pDrawable -> pScreen, &tmpRegion, NullBox, 1); + + REGION_INTERSECT(pDrawable -> pScreen, &tmpRegion, pResource -> region, pRegion); + + if (REGION_NIL(&tmpRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentValidateSplit: Marking the overlapping commits as invalid " + "for drawable at [%p].\n", (void *) pDrawable); + #endif + + nxagentReleaseSplit(pDrawable); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentValidateSplit: Leaving the commits as valid for " + "drawable at [%p].\n", (void *) pDrawable); + } + #endif + + REGION_UNINIT(pDrawable -> pScreen, &tmpRegion); + } +} + +void nxagentFreeSplit(int resource) +{ + DrawablePtr pDrawable; + + SplitResourcePtr pResource = &nxagentSplitResources[resource]; + + if (pResource == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentFreeSplit: PANIC! No valid split record for resource [%d].\n", + resource); + #endif + + FatalError("nxagentFreeSplit: PANIC! No valid split record for resource [%d].\n", + resource); + } + else if (pResource -> split != resource) + { + #ifdef PANIC + fprintf(stderr, "nxagentFreeSplit: PANIC! The record [%d] doesn't match the resource [%d].\n", + pResource -> split, resource); + #endif + + FatalError("nxagentFreeSplit: PANIC! The record [%d] doesn't match the resource [%d].\n", + pResource -> split, resource); + } + + pDrawable = pResource -> drawable; + + if (pDrawable != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentFreeSplit: Removing association to drawable at [%p].\n", + (void *) pDrawable); + #endif + + nxagentReleaseSplit(pDrawable); + } + #ifdef TEST + else + { + /* + * The end of the split has come after we have + * invalidated the operation and removed the + * association to the drawable. This happens, + * for example, if the drawable is destroyed. + */ + + fprintf(stderr, "nxagentFreeSplit: WARNING! Releasing invalidated resource [%d].\n", + pResource -> split); + } + #endif + + #ifdef TEST + fprintf(stderr, "nxagentFreeSplit: Freeing the record for resource [%d].\n", + pResource -> split); + #endif + + nxagentFreeSplitResource(pResource); +} + +/* +FIXME: This must be enabled when the vanilla + synchronization procedure is working. +*/ +#define USE_FINISH_SPLIT + +void nxagentWaitDrawable(DrawablePtr pDrawable) +{ + SplitResourcePtr pResource; + + pDrawable = nxagentSplitDrawable(pDrawable); + + pResource = nxagentSplitResource(pDrawable); + + if (pResource == NULL) + { + #ifdef TEST + fprintf(stderr, "++++++nxagentWaitDrawable: WARNING! The drawable at [%p] is already awake.\n", + (void *) pDrawable); + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "++++++nxagentWaitDrawable: Waiting drawable at [%p] with resource [%d].\n", + (void *) pDrawable, pResource -> split); + #endif + + /* + * Be sure we intercept an I/O error + * as well as an interrupt. + */ + + #ifdef USE_FINISH_SPLIT + + NXFinishSplit(nxagentDisplay, pResource -> split); + + #endif + + NXFlushDisplay(nxagentDisplay, NXFlushBuffer); + + for (;;) + { + /* + * Handling all the possible events here + * preempts the queue and makes a better + * use of the link. + * + * We should better use XIfEvent() instead + * of looping again and again through the + * event queue. + */ + + nxagentDispatchEvents(NULL); + + /* + * Wait indefinitely until the resource + * is released or the display is shut + * down. + */ + + if (nxagentSplitResource(pDrawable) == NULL || + NXDisplayError(nxagentDisplay) == 1) + { + #ifdef TEST + + if (NXDisplayError(nxagentDisplay) == 1) + { + fprintf(stderr, "++++++nxagentWaitDrawable: WARNING! Display error detected while " + "waiting for the drawable.\n"); + } + else + { + fprintf(stderr, "++++++nxagentWaitDrawable: Drawable at [%p] can now be restarted.\n", + (void *) pDrawable); + } + + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "++++++nxagentWaitDrawable: Yielding control to the NX transport.\n"); + #endif + + nxagentWaitEvents(nxagentDisplay, NULL); + } +} + +static Bool nxagentCommitSplitPredicate(Display *display, XEvent *event, XPointer ptr) +{ + return (event -> type == ClientMessage && + event -> xclient.data.l[0] == NXCommitSplitNotify && + event -> xclient.window == 0 && event -> xclient.message_type == 0 && + event -> xclient.format == 32); +} + +void nxagentWaitCommitEvent(int resource) +{ + XEvent event; + + /* + * Check if there is any commit pending. As + * we are at it, handle any commit, even those + * commits pertaining to other resources. + * + * We can receive some commits even if we'll + * later receive a no-split event. The proxy, + * in fact, may have missed to find the image + * in the memory cache and could have loaded it + * from disk (so requiring a commit) before we + * marked the end of the split sequence. + */ + + while (nxagentCheckEvents(nxagentDisplay, &event, + nxagentCommitSplitPredicate, NULL) == 1) + { + int client = event.xclient.data.l[1]; + int request = event.xclient.data.l[2]; + int position = event.xclient.data.l[3]; + + #ifdef TEST + fprintf(stderr, "nxagentWaitCommitEvent: Commit event received with " + "client [%d] request [%d] and position [%d].\n", + client, request, position); + #endif + + nxagentHandleCommitSplitEvent(client, request, position); + } +} + +static Bool nxagentWaitSplitPredicate(Display *display, XEvent *event, XPointer ptr) +{ + return (event -> type == ClientMessage && + (event -> xclient.data.l[0] == NXNoSplitNotify || + event -> xclient.data.l[0] == NXStartSplitNotify) && + event -> xclient.window == 0 && event -> xclient.message_type == 0 && + event -> xclient.format == 32); +} + +int nxagentWaitSplitEvent(int resource) +{ + XEvent event; + + int split = 0; + + /* + * Don't flush the link. We only want to + * query the NX transport to check whether + * the operation caused a split. + */ + + NXFlushDisplay(nxagentDisplay, NXFlushBuffer); + + for (;;) + { + #ifdef TEST + fprintf(stderr, "nxagentWaitSplitEvent: Waiting for the split event for resource [%d].\n", + resource); + #endif + + XIfEvent(nxagentDisplay, &event, nxagentWaitSplitPredicate, NULL); + + if (NXDisplayError(nxagentDisplay) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentWaitSplitEvent: WARNING! Error detected reading the event.\n"); + #endif + + nxagentHandleNoSplitEvent(resource); + + break; + } + + #ifdef TEST + fprintf(stderr, "nxagentWaitSplitEvent: Going to process the split event.\n"); + #endif + + if (resource != (int) event.xclient.data.l[1]) + { + #ifdef PANIC + fprintf(stderr, "nxagentWaitSplitEvent: PANIC! Got event for resource [%d] while " + "waiting for resource [%d].\n", (int) event.xclient.data.l[1], resource); + + fprintf(stderr, "nxagentWaitSplitEvent: PANIC! Restarting resource [%d] due to the " + "missing split event.\n", resource); + #endif + + nxagentHandleNoSplitEvent(resource); + + break; + } + else if (event.xclient.data.l[0] == NXNoSplitNotify) + { + nxagentHandleNoSplitEvent(resource); + + break; + } + else + { + nxagentHandleStartSplitEvent(resource); + + split = 1; + + break; + } + } + + return split; +} + +void nxagentHandleNoSplitEvent(int resource) +{ + if (resource >= 0 && resource < NXNumberOfResources) + { + #ifdef TEST + + SplitResourcePtr pResource = &nxagentSplitResources[resource]; + + fprintf(stderr, "nxagentHandleNoSplitEvent: Received event for resource [%d].\n", + resource); + + nxagentCheckResource(pResource, resource); + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentHandleNoSplitEvent: Checking if there is any commit pending.\n"); + #endif + + nxagentWaitCommitEvent(resource); + + #ifdef TEST + fprintf(stderr, "nxagentHandleNoSplitEvent: No streaming was required with resource [%d] " + "and drawable at [%p].\n", resource, (void *) pResource -> drawable); + #endif + + /* + * Release the resource. + */ + + nxagentFreeSplit(resource); + } + #ifdef PANIC + else + { + fprintf(stderr, "nxagentHandleNoSplitEvent: PANIC! Invalid resource identifier [%d] " + " received in event.\n", resource); + } + #endif +} + +void nxagentHandleStartSplitEvent(int resource) +{ + if (resource >= 0 && resource < NXNumberOfResources) + { + #ifdef TEST + + SplitResourcePtr pResource = &nxagentSplitResources[resource]; + + fprintf(stderr, "nxagentHandleStartSplitEvent: Received event for resource [%d].\n", + resource); + + nxagentCheckResource(pResource, resource); + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentHandleStartSplitEvent: Checking if there is any commit pending.\n"); + #endif + + nxagentWaitCommitEvent(resource); + + #ifdef TEST + fprintf(stderr, "nxagentHandleStartSplitEvent: Streaming started with resource [%d] " + "and drawable at [%p].\n", resource, (void *) pResource -> drawable); + #endif + } + #ifdef PANIC + else + { + fprintf(stderr, "nxagentHandleStartSplitEvent: PANIC! Invalid resource identifier [%d] " + " received in event.\n", resource); + } + #endif +} + +void nxagentHandleCommitSplitEvent(int resource, int request, int position) +{ + if (resource >= 0 && resource < NXNumberOfResources && + request >= 0 && position >= 0) + { + SplitResourcePtr pResource = &nxagentSplitResources[resource]; + + #ifdef TEST + fprintf(stderr, "nxagentHandleCommitSplitEvent: Received event for resource [%d].\n", + resource); + #endif + + if (pResource != NULL && pResource -> commit == 1) + { + #ifdef TEST + + nxagentCheckResource(pResource, resource); + + fprintf(stderr, "nxagentHandleCommitSplitEvent: Committing request [%d] with " + "position [%d] for resource [%d].\n", request, position, resource); + + #endif + + NXCommitSplit(nxagentDisplay, resource, 1, request, position); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentHandleCommitSplitEvent: Discarding request [%d] for " + "resource [%d] with position [%d].\n", request, resource, position); + #endif + + NXCommitSplit(nxagentDisplay, resource, 0, request, position); + } + } + #ifdef PANIC + else + { + fprintf(stderr, "nxagentHandleCommitSplitEvent: PANIC! Invalid commit event with " + "request [%d] and position [%d] for resource [%d].\n", request, + position, resource); + } + #endif +} + +void nxagentHandleEndSplitEvent(int resource) +{ + if (resource >= 0 && resource < NXNumberOfResources) + { + SplitResourcePtr pResource = &nxagentSplitResources[resource]; + + #ifdef TEST + fprintf(stderr, "nxagentHandleEndSplitEvent: Received event for resource [%d].\n", + resource); + + nxagentCheckResource(pResource, resource); + + #endif + + #ifdef TEST + fprintf(stderr, "nxagentHandleEndSplitEvent: Checking if there is any commit pending.\n"); + #endif + + nxagentWaitCommitEvent(resource); + + if (pResource != NULL && pResource -> commit == 1) + { + #ifdef TEST + + fprintf(stderr, "nxagentHandleEndSplitEvent: Checking the split region at [%p] " + "for drawable at [%p].\n", (void *) pResource -> drawable, + (void *) pResource -> region); + + if (pResource -> region == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! Invalid region [%p] for drawable at [%p].\n", + (void *) pResource -> region, (void *) pResource -> drawable); + #endif + + FatalError("nxagentHandleEndSplitEvent: PANIC! Invalid region [%p] for drawable at [%p].\n", + (void *) pResource -> region, (void *) pResource -> drawable); + } + else if (pResource -> gc == NULL) + { + #ifdef PANIC + fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! Invalid GC [%p] for drawable at [%p].\n", + (void *) pResource -> gc, (void *) pResource -> drawable); + #endif + + FatalError("nxagentHandleEndSplitEvent: PANIC! Invalid GC [%p] for drawable at [%p].\n", + (void *) pResource -> gc, (void *) pResource -> drawable); + } + + #endif + + if (pResource -> drawable != NULL && + pResource -> region != NullRegion) + { + if (REGION_NIL(pResource -> region) == 0) + { + REGION_SUBTRACT(pResource -> drawable -> pScreen, + nxagentCorruptedRegion(pResource -> drawable), + nxagentCorruptedRegion(pResource -> drawable), + pResource -> region); + +/* +FIXME: Implementing the valid region policy + + nxagentExpandValidRegion(pResource -> drawable, pResource -> region); +*/ + + #ifdef TEST + fprintf(stderr, "nxagentHandleEndSplitEvent: Synchronized region [%d,%d,%d,%d] " + "for drawable at [%p].\n", pResource -> region -> extents.x1, + pResource -> region -> extents.y1, pResource -> region -> extents.x2, + pResource -> region -> extents.y2, (void *) pResource -> drawable); + #endif + } + else + { + #ifdef PANIC + fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! The region [%d,%d,%d,%d] for drawable " + "at [%p] is empty.\n", pResource -> region -> extents.x1, + pResource -> region -> extents.y1, pResource -> region -> extents.x2, + pResource -> region -> extents.y2, (void *) pResource -> drawable); + #endif + + FatalError("nxagentHandleEndSplitEvent: PANIC! The region [%d,%d,%d,%d] for drawable " + "at [%p] is empty.\n", pResource -> region -> extents.x1, + pResource -> region -> extents.y1, pResource -> region -> extents.x2, + pResource -> region -> extents.y2, (void *) pResource -> drawable); + } + } + else + { + #ifdef PANIC + fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! Invalid record for resource [%d] with " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + resource, pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + #endif + + FatalError("nxagentHandleEndSplitEvent: PANIC! Invalid record for resource [%d] with " + "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n", + resource, pResource -> pending, pResource -> split, pResource -> unpack, + (void *) pResource -> drawable, (void *) pResource -> region, + pResource -> commit, (void *) pResource -> gc); + } + } + + /* + * Release the resource. + */ + + nxagentFreeSplit(resource); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentHandleEndSplitEvent: WARNING! Ignoring split event " + "for resource [%d].\n", resource); + } + #endif +} + +void nxagentHandleEmptySplitEvent() +{ +/* +FIXME: Should run a consistency check here. +*/ + #ifdef TEST + fprintf(stderr, "nxagentHandleEmptySplitEvent: No more split event to handle.\n"); + #endif +} + +/* + * The drawable is going to become corrupted. + */ + +void nxagentSetCorruptedTimestamp(DrawablePtr pDrawable) +{ + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentSetCorruptedTimestamp: Corruption timestamp for pixmap at [%p] was [%lu].\n", + (void *) pDrawable, nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp); + #endif + + nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp = GetTimeInMillis(); + + #ifdef TEST + fprintf(stderr, "nxagentSetCorruptedTimestamp: New corruption timestamp for pixmap at [%p] is [%lu].\n", + (void *) pDrawable, nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp); + #endif + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentSetCorruptedTimestamp: Corruption timestamp for window at [%p] was [%lu].\n", + (void *) pDrawable, nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp); + #endif + + nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp = GetTimeInMillis(); + + #ifdef TEST + fprintf(stderr, "nxagentSetCorruptedTimestamp: New corruption timestamp for window at [%p] is [%lu].\n", + (void *) pDrawable, nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp); + #endif + } + } +} + +/* + * Reset the timestamp taken when the drawable + * became initially corrupted. The timestamp is + * reset only after the drawable has been fully + * synchronized. + */ + +void nxagentResetCorruptedTimestamp(DrawablePtr pDrawable) +{ + if (nxagentDrawableStatus(pDrawable) == Synchronized) + { + if (pDrawable -> type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentResetCorruptedTimestamp: Corruption timestamp for pixmap at [%p] was [%lu].\n", + (void *) pDrawable, nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp); + #endif + + nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp = 0; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentResetCorruptedTimestamp: Corruption timestamp for window at [%p] was [%lu].\n", + (void *) pDrawable, nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp); + #endif + + nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp = 0; + } + } +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Split.h b/nx-X11/programs/Xserver/hw/nxagent/Split.h new file mode 100644 index 000000000..397feef16 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Split.h @@ -0,0 +1,84 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Split_H__ +#define __Split_H__ + +typedef struct _SplitResourceRec +{ + int pending; + int split; + int unpack; + DrawablePtr drawable; + RegionPtr region; + GCPtr gc; + int commit; + +} SplitResourceRec; + +typedef SplitResourceRec *SplitResourcePtr; + +extern SplitResourceRec nxagentSplitResources[]; + +typedef struct _UnpackResourceRec +{ + int pending; + int unpack; + DrawablePtr drawable; + +} UnpackResourceRec; + +typedef UnpackResourceRec *UnpackResourcePtr; + +extern UnpackResourceRec nxagentUnpackResources[]; + +void nxagentInitSplitResources(); +void nxagentInitUnpackResources(); + +SplitResourcePtr nxagentAllocSplitResource(); +void nxagentFreeSplitResource(SplitResourcePtr pResource); + +UnpackResourcePtr nxagentAllocUnpackResource(); +void nxagentFreeUnpackResource(UnpackResourcePtr pResource); + +#define nxagentSplitResource(pDrawable) \ + ((pDrawable) -> type == DRAWABLE_PIXMAP ? \ + (nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> splitResource) : \ + (nxagentWindowPriv((WindowPtr) pDrawable) -> splitResource)) + +/* +FIXME: Make it a real function to log a warning + in the logs. + +#define nxagentSplitDrawable(pDrawable) \ + (((pDrawable) -> type == DRAWABLE_PIXMAP && \ + nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) ? \ + (DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable) : pDrawable) +*/ +DrawablePtr nxagentSplitDrawable(DrawablePtr pDrawable); + +int nxagentCreateSplit(DrawablePtr pDrawable, GCPtr *pGC); +void nxagentRegionSplit(DrawablePtr pDrawable, RegionPtr pRegion); +void nxagentValidateSplit(DrawablePtr pDrawable, RegionPtr pRegion); +void nxagentReleaseSplit(DrawablePtr pDrawable); + +void nxagentReleaseAllSplits(void); + +void nxagentSetCorruptedTimestamp(DrawablePtr pDrawable); +void nxagentResetCorruptedTimestamp(DrawablePtr pDrawable); + +#endif /* __Split_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/TestExt.c b/nx-X11/programs/Xserver/hw/nxagent/TestExt.c new file mode 100644 index 000000000..704c63e51 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/TestExt.c @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include +#include +#include +#undef Bool +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "mipointer.h" +#define XTestSERVER_SIDE +#include "xtestext1.h" + +extern CARD32 nxagentLastEventTime; + +void XTestGetPointerPos(short *fmousex, short *fmousey); + +void XTestJumpPointer(int jx, int jy, int dev_type); + +void XTestGenerateEvent(int dev_type, int keycode, int keystate, + int mousex, int mousey); + +void XTestGetPointerPos(short *fmousex, short *fmousey) +{ + int x,y; + + miPointerPosition(&x, &y); + *fmousex = x; + *fmousey = y; +} + +void XTestJumpPointer(int jx, int jy, int dev_type) +{ + miPointerAbsoluteCursor(jx, jy, GetTimeInMillis()); +} + +void XTestGenerateEvent(int dev_type, int keycode, int keystate, + int mousex, int mousey) +{ +/* + xEvent tevent; + + tevent.u.u.type = (dev_type == XE_POINTER) ? + (keystate == XTestKEY_UP) ? ButtonRelease : ButtonPress : + (keystate == XTestKEY_UP) ? KeyRelease : KeyPress; + tevent.u.u.detail = keycode; + tevent.u.keyButtonPointer.rootX = mousex; + tevent.u.keyButtonPointer.rootY = mousey; + tevent.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis(); + mieqEnqueue(&tevent); +*/ +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.c b/nx-X11/programs/Xserver/hw/nxagent/Trap.c new file mode 100644 index 000000000..3b801d803 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.c @@ -0,0 +1,99 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "Trap.h" + +/* + * Set if we are dispatching a render + * extension request. Used to avoid + * reentrancy in GC operations. + */ + +int nxagentGCTrap = 0; + +/* + * Set if we are enqueing an internal + * operation, CreateWindow and Reparent- + * Window. Used to remove any screen operation. + */ + +int nxagentScreenTrap = 0; + +/* + * Set if we detected that our RENDER + * implementation is faulty. + */ + +int nxagentRenderTrap = 0; + +/* + * Set if we are executing a GC operation + * only on the X side. Used to avoid + * reentrancy in FB layer. + */ + +int nxagentFBTrap = 0; + +/* + * Set if we are dispatching a shared + * memory extension request. + */ + +int nxagentShmTrap = 0; + +/* + * Set if a shared pixmap operation is + * requested by the client. + */ + +int nxagentShmPixmapTrap = 0; + +/* + * Set if we are dispatching a XVideo + * extension request. + */ + +int nxagentXvTrap = 0; + +/* + * Set if we are dispatching a GLX + * extension request. + */ + +int nxagentGlxTrap = 0; + +/* + * Set while we are resuming the session. + */ + +int nxagentReconnectTrap = 0; + +/* + * Set if we need to realize a drawable + * by using a lossless encoding. + */ + +int nxagentLosslessTrap = 0; + +/* + * Set to force the synchronization of + * a drawable. + */ + +int nxagentSplitTrap = 0; + + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.h b/nx-X11/programs/Xserver/hw/nxagent/Trap.h new file mode 100644 index 000000000..f699306ab --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.h @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Traps_H__ +#define __Traps_H__ + +/* + * Set if we are dispatching a render + * extension request. Used to avoid + * reentrancy in GC operations. + */ + +extern int nxagentGCTrap; + +/* + * Set if we are enqueing an internal + * operation, CreateWindow and Reparent- + * Window. Used to remove any screen operation. + */ + +extern int nxagentScreenTrap; + +/* + * Set if we detected that our RENDER + * implementation is faulty. + */ + +extern int nxagentRenderTrap; + +/* + * Set if we are executing a GC operation + * only on the X side. Used to avoid + * reentrancy in FB layer. + */ + +extern int nxagentFBTrap; + +/* + * Set if we are dispatching a shared + * memory extension request. + */ + +extern int nxagentShmTrap; + +/* + * Set if a shared pixmap operation is + * requested by the client. + */ + +extern int nxagentShmPixmapTrap; + +/* + * Set if we are dispatching a XVideo + * extension request. + */ + +extern int nxagentXvTrap; + +/* + * Set if we are dispatching a GLX + * extension request. + */ + +extern int nxagentGlxTrap; + +/* + * Set while we are resuming the session. + */ + +extern int nxagentReconnectTrap; + +/* + * Set if we need to realize a drawable + * by using a lossless encoding. + */ + +extern int nxagentLosslessTrap; + +/* + * Set to force the synchronization of + * a drawable. + */ + +extern int nxagentSplitTrap; + +#endif /* __Trap_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Utils.h b/nx-X11/programs/Xserver/hw/nxagent/Utils.h new file mode 100644 index 000000000..9334a7868 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Utils.h @@ -0,0 +1,39 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Utils_H__ +#define __Utils_H__ + +/* + * Number of bits in fixed point operations. + */ + +#define PRECISION 16 + +/* + * "1" ratio means "don't scale". + */ + +#define DONT_SCALE (1 << PRECISION) + +#define nxagentScale(i, ratio) (((i) * (ratio)) >> (PRECISION)) + +#ifndef MIN +#define MIN(A, B) ( (A) < (B) ? (A) : (B) ) +#endif + +#endif /* __Utils_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Visual.c b/nx-X11/programs/Xserver/hw/nxagent/Visual.c new file mode 100644 index 000000000..2a8283a30 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Visual.c @@ -0,0 +1,159 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "scrnintstr.h" +#include "dix.h" +#include "mi.h" +#include "mibstore.h" +#include "resource.h" + +#include "X.h" +#include "Xproto.h" + +#include "Agent.h" +#include "Display.h" +#include "Visual.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Predefined visual used for drawables + * having a 32 bits depth. + */ + +Visual nxagentAlphaVisual; + +Visual *nxagentVisual(VisualPtr pVisual) +{ + XVisualInfo visual; + + int i; + + visual.class = pVisual->class; + visual.bits_per_rgb = pVisual->bitsPerRGBValue; + visual.colormap_size = pVisual->ColormapEntries; + visual.depth = pVisual->nplanes; + visual.red_mask = pVisual->redMask; + visual.green_mask = pVisual->greenMask; + visual.blue_mask = pVisual->blueMask; + + for (i = 0; i < nxagentNumVisuals; i++) + { + if (nxagentCompareVisuals(visual, nxagentVisuals[i]) == 1) + { + return nxagentVisuals[i].visual; + } + } + + return NULL; +} + +Visual *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual) +{ + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + { + if (pScreen->visuals[i].vid == visual) + { + return nxagentVisual(&pScreen->visuals[i]); + } + } + + return NULL; +} + +Colormap nxagentDefaultVisualColormap(Visual *visual) +{ + int i; + + for (i = 0; i < nxagentNumVisuals; i++) + { + if (nxagentVisuals[i].visual == visual) + { + return nxagentDefaultColormaps[i]; + } + } + + return None; +} + +/* + * This is currently unused. It should serve + * the scope of matching a visual whenever + * a drawable has a different depth than the + * real display. + */ + +Visual *nxagentVisualFromDepth(ScreenPtr pScreen, int depth) +{ + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + { + if (pScreen->visuals[i].nplanes == depth) + { + return nxagentVisual(&pScreen->visuals[i]); + } + } + + return NULL; +} + +/* + * Create a fake 32 bits depth visual and + * initialize it based on the endianess + * of the remote display. + */ + +void nxagentInitAlphaVisual() +{ + nxagentAlphaVisual.visualid = XAllocID(nxagentDisplay); + + /* + * Color masks are referred to bits inside + * the pixel. This is independent from the + * endianess. + */ + + nxagentAlphaVisual.red_mask = 0x00ff0000; + nxagentAlphaVisual.green_mask = 0x0000ff00; + nxagentAlphaVisual.blue_mask = 0x000000ff; + + #ifdef TEST + fprintf(stderr,"nxagentInitAlphaVisual: Set alpha visual with id [0x%lx] mask [0x%lx,0x%lx,0x%lx].\n", + nxagentAlphaVisual.visualid, nxagentAlphaVisual.red_mask, + nxagentAlphaVisual.green_mask, nxagentAlphaVisual.blue_mask); + #endif +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/Visual.h b/nx-X11/programs/Xserver/hw/nxagent/Visual.h new file mode 100644 index 000000000..6d8a8742d --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Visual.h @@ -0,0 +1,73 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifndef __Visual_H__ +#define __Visual_H__ + +Visual *nxagentVisual(VisualPtr pVisual); +Visual *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual); +Visual *nxagentVisualFromDepth(ScreenPtr pScreen, int depth); + +Colormap nxagentDefaultVisualColormap(Visual *visual); + +#define nxagentDefaultVisual(pScreen) \ + nxagentVisualFromID((pScreen), (pScreen) -> rootVisual) + +/* + * Visual generated by Xorg and Xfree86 at + * 16-bit depth differs on the bits_per_rgb + * value, so we avoid checking it. + */ + +/* + * Some Solaris X servers uses the color + * masks inverted, so that the red and + * the blue mask are switched. To reconnect + * the session on this displays, we do a + * double check, as workaround. + */ + +#define nxagentCompareVisuals(v1, v2) \ + ((v1).depth == (v2).depth && \ + /*(v1).bits_per_rgb == (v2).bits_per_rgb &&*/ \ + (v1).class == (v2).class && \ + ((v1).red_mask == (v2).red_mask || \ + (v1).red_mask == (v2).blue_mask) && \ + (v1).green_mask == (v2).green_mask && \ + ((v1).blue_mask == (v2).blue_mask || \ + (v1).blue_mask == (v2).red_mask) && \ + (v1).colormap_size == (v2).colormap_size) + +Visual nxagentAlphaVisual; + +void nxagentInitAlphaVisual(); + +#endif /* __Visual_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/Window.c b/nx-X11/programs/Xserver/hw/nxagent/Window.c new file mode 100644 index 000000000..ff775f272 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Window.c @@ -0,0 +1,3614 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include + +#include "X.h" +#include "Xproto.h" +#include "gcstruct.h" +#include "../../include/window.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "region.h" +#include "dixstruct.h" +#include "selection.h" +#include "mi.h" +#include "fb.h" +#include "mibstorest.h" + +#include "Agent.h" +#include "Display.h" +#include "Screen.h" +#include "GCs.h" +#include "GCOps.h" +#include "Drawable.h" +#include "Colormap.h" +#include "Cursor.h" +#include "Visual.h" +#include "Events.h" +#include "Clipboard.h" +#include "Args.h" +#include "Trap.h" +#include "Rootless.h" +#include "Atoms.h" +#include "Client.h" +#include "Reconnect.h" +#include "Dialog.h" +#include "Splash.h" +#include "Holder.h" +#include "Init.h" +#include "Composite.h" +#include "Events.h" + +#include "NX.h" +#include "NXlib.h" + +#include "Xatom.h" + +/* + * Used to register the window's privates. + */ + +int nxagentWindowPrivateIndex; + +/* + * Number of windows which need synchronization. + */ + +int nxagentCorruptedWindows; + +/* + * Used to track nxagent window's visibility. + */ + +int nxagentVisibility = VisibilityUnobscured; +unsigned long nxagentVisibilityTimeout = 0; +Bool nxagentVisibilityStop = False; + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Useful to test the window configuration + * failures. + */ + +#ifdef TEST +#define MAKE_SYNC_CONFIGURE_WINDOW XSync(nxagentDisplay, 0) +#else +#define MAKE_SYNC_CONFIGURE_WINDOW +#endif + +extern WindowPtr nxagentViewportFrameLeft; +extern WindowPtr nxagentViewportFrameRight; +extern WindowPtr nxagentViewportFrameAbove; +extern WindowPtr nxagentViewportFrameBelow; + +extern WindowPtr nxagentRootTileWindow; + +/* + * Also referenced in Events.c. + */ + +int nxagentSplashCount = 0; + +#define RECTLIMIT 25 +#define BSPIXMAPLIMIT 128 + +Bool nxagentExposeArrayIsInitialized = False; +Window nxagentConfiguredSynchroWindow; +static int nxagentExposeSerial = 0; + +StoringPixmapPtr nxagentBSPixmapList[BSPIXMAPLIMIT]; + +/* + * Used to walk through the window hierarchy + * to find a window + */ + +typedef struct _WindowMatch +{ + WindowPtr pWin; + Window id; + +} WindowMatchRec; + +Bool nxagentReconnectAllWindows(void *); + +Bool nxagentDisconnectAllWindows(void); + +Bool nxagentIsIconic(WindowPtr); + +/* + * From NXproperty.c. + */ + +int GetWindowProperty(WindowPtr, Atom, long, long, Bool, Atom, Atom*, int*, + unsigned long*, unsigned long*, unsigned char**); + +/* + * From NXwindow.c. + */ + +void nxagentClearSplash(WindowPtr pWin); + +/* + * Other local functions. + */ + +static Bool nxagentSomeWindowsAreMapped(void); + +static void nxagentFrameBufferPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); + +static void nxagentTraverseWindow(WindowPtr, void(*)(pointer, XID, pointer), pointer); + +static void nxagentDisconnectWindow(pointer, XID, pointer); + +static Bool nxagentLoopOverWindows(void(*)(pointer, XID, pointer)); + +static void nxagentReconfigureWindowCursor(pointer, XID, pointer); + +static void nxagentReconnectWindow(pointer, XID, pointer); + +static void nxagentReconfigureWindow(pointer, XID, pointer); + +static int nxagentForceExposure(WindowPtr pWin, pointer ptr); + +/* + * This is currently unused. + */ + +#ifdef TEST + +static Bool nxagentCheckWindowIntegrity(WindowPtr pWin); + +#endif + +WindowPtr nxagentGetWindowFromID(Window id) +{ + WindowPtr pWin = WindowTable[0]; + + while (pWin && nxagentWindowPriv(pWin)) + { + if (nxagentWindow(pWin) == id) + { + return pWin; + } + + if (pWin -> nextSib) + { + pWin = pWin -> nextSib; + } + else + { + pWin = pWin -> firstChild; + } + } + + return NULL; +} + +static int nxagentFindWindowMatch(WindowPtr pWin, pointer ptr) +{ + WindowMatchRec *match = (WindowMatchRec *) ptr; + + if (match -> id == nxagentWindow(pWin)) + { + match -> pWin = pWin; + + return WT_STOPWALKING; + } + else + { + return WT_WALKCHILDREN; + } +} + +WindowPtr nxagentWindowPtr(Window window) +{ + int i; + + WindowMatchRec match; + + match.pWin = NullWindow; + match.id = window; + + for (i = 0; i < nxagentNumScreens; i++) + { + WalkTree(screenInfo.screens[i], nxagentFindWindowMatch, (pointer) &match); + + if (match.pWin) break; + } + + return match.pWin; +} + +Bool nxagentCreateWindow(pWin) + WindowPtr pWin; +{ + unsigned long mask; + XSetWindowAttributes attributes; + Visual *visual; + ColormapPtr pCmap; + + if (nxagentScreenTrap) + { + return True; + } + + nxagentSplashCount++; + + if (nxagentSplashCount == 2) + { + nxagentClearSplash(nxagentRootTileWindow); + } +#ifdef NXAGENT_LOGO_DEBUG + fprintf(stderr, "nxagentSplashCount: %d\n", nxagentSplashCount); +#endif + + if (pWin->drawable.class == InputOnly) { + mask = CWEventMask; + visual = CopyFromParent; + } + else { + mask = CWEventMask | CWBackingStore; + + if (pWin->optional) + { + mask |= CWBackingPlanes | CWBackingPixel; + attributes.backing_planes = pWin->optional->backingBitPlanes; + attributes.backing_pixel = pWin->optional->backingPixel; + } + + attributes.backing_store = NotUseful; + + #ifdef TEST + fprintf(stderr, "nxagentCreateWindow: Backing store on window at %p is %d.\n", + (void*)pWin, attributes.backing_store); + #endif + +/* +FIXME: We need to set save under on the real display? +*/ + if (nxagentSaveUnder == True) + { + mask |= CWSaveUnder; + attributes.save_under = False; + } + + if (pWin->parent) { + if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent)) { + visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); + mask |= CWColormap; + if (pWin->optional->colormap) { + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP); + attributes.colormap = nxagentColormap(pCmap); + } + else + attributes.colormap = nxagentDefaultVisualColormap(visual); + } + else if (pWin->optional) + visual = CopyFromParent; + else { + visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); + mask |= CWColormap; + attributes.colormap = nxagentDefaultVisualColormap(visual); + } + } + else { /* root windows have their own colormaps at creation time */ + visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP); + mask |= CWColormap; + attributes.colormap = nxagentColormap(pCmap); + } + } + + if (mask & CWEventMask) + { + nxagentGetEventMask(pWin, (Mask*)&attributes.event_mask); + } + #ifdef WARNING + else + { + attributes.event_mask = NoEventMask; + } + #endif + + /* + * Select the event mask if window is a top level + * window. This at least makes the keyboard barely + * work. + */ + + #ifdef TEST + fprintf(stderr, "nxagentCreateWindow: Going to create new window.\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentCreateWindow: Creating %swindow at %p current event mask = %lX mask & CWEventMask = %ld " + "event_mask = %lX\n", + nxagentWindowTopLevel(pWin) ? "toplevel " : "", (void*)pWin, pWin -> eventMask, + mask & CWEventMask, attributes.event_mask); + + fprintf(stderr, "nxagentCreateWindow: position [%d,%d] size [%d,%d] depth [%d] border [%d] class [%d].\n", + pWin->origin.x - wBorderWidth(pWin), pWin->origin.y - wBorderWidth(pWin), + pWin->drawable.width, pWin->drawable.height, pWin->drawable.depth, pWin->borderWidth, + pWin->drawable.class); + #endif + + nxagentWindowPriv(pWin)->window = XCreateWindow(nxagentDisplay, + nxagentWindowParent(pWin), + pWin->origin.x - + wBorderWidth(pWin), + pWin->origin.y - + wBorderWidth(pWin), + pWin->drawable.width, + pWin->drawable.height, + pWin->borderWidth, + pWin->drawable.depth, + pWin->drawable.class, + visual, + mask, &attributes); + + nxagentWindowPriv(pWin) -> isMapped = 0; + nxagentWindowPriv(pWin) -> isRedirected = 0; + + nxagentWindowPriv(pWin) -> visibilityState = VisibilityUnobscured; + + nxagentWindowPriv(pWin) -> corruptedRegion = REGION_CREATE(pWin -> drawable.pScreen, NULL, 1); + + nxagentWindowPriv(pWin) -> hasTransparentChildren = 0; + + nxagentWindowPriv(pWin) -> containGlyphs = 0; + + nxagentWindowPriv(pWin) -> corruptedId = 0; + + nxagentWindowPriv(pWin) -> deferredBackgroundExpose = 0; + + nxagentWindowPriv(pWin) -> synchronizationBitmap = NullPixmap; + + nxagentWindowPriv(pWin) -> corruptedTimestamp = 0; + + nxagentWindowPriv(pWin) -> splitResource = NULL; + + if (nxagentOption(Rootless) == 1) + { + if (pWin != nxagentRootlessWindow) + { + WindowPtr pParent = pWin -> parent; + + if (pParent && nxagentWindowPriv(pParent) -> isMapped == 1) + { + nxagentWindowPriv(pWin) -> isMapped = 1; + } + else + { + nxagentWindowPriv(pWin) -> isMapped = 0; + } + } + else + { + nxagentWindowPriv(pWin) -> isMapped = 0; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentCreateWindow: Created new window with id [%ld].\n", + nxagentWindowPriv(pWin)->window); + #endif + + /* + * Set the WM_DELETE_WINDOW protocols on every + * top level window. Also redirect the window + * if it is a top level. + */ + + if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin)) + { + Atom prop = nxagentMakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), True); + + XlibAtom atom = nxagentMakeAtom("WM_DELETE_WINDOW", strlen("WM_DELETE_WINDOW"), True); + + XSetWMProtocols(nxagentDisplay, nxagentWindowPriv(pWin)->window, &atom, 1); + + nxagentAddPropertyToList(prop, pWin); + + /* + * Redirect the window to the off-screen + * memory, if the composite extension is + * supported on the display. + */ +/* +FIXME: Do all the windows for which nxagentWindowTopLevel(pWin) + returns true need to be redirected? +*/ + nxagentRedirectWindow(pWin); + } + + nxagentWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin); + nxagentWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin); + nxagentWindowPriv(pWin)->width = pWin->drawable.width; + nxagentWindowPriv(pWin)->height = pWin->drawable.height; + nxagentWindowPriv(pWin)->borderWidth = pWin->borderWidth; + nxagentWindowPriv(pWin)->siblingAbove = None; + nxagentWindowPriv(pWin)->pPicture = NULL; + + if (nxagentRootTileWindow) + { + if (nxagentWindowPriv(pWin)->window != nxagentWindowPriv(nxagentRootTileWindow)->window) + { + XClearWindow(nxagentDisplay, nxagentWindowPriv(nxagentRootTileWindow)->window); + } + } + + if (pWin->nextSib) + { + nxagentWindowPriv(pWin->nextSib)->siblingAbove = nxagentWindow(pWin); + } + +#ifdef NXAGENT_SHAPE2 +#ifdef SHAPE + nxagentWindowPriv(pWin)->boundingShape = NULL; + nxagentWindowPriv(pWin)->clipShape = NULL; +#endif /* SHAPE */ +#else +#ifdef SHAPE + nxagentWindowPriv(pWin)->boundingShape = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); + nxagentWindowPriv(pWin)->clipShape = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); +#endif /* SHAPE */ +#endif + + fbCreateWindow(pWin); + + /* + * Only the root window will have + * the right colormap. + */ + + if (!pWin->parent) + { + nxagentSetInstalledColormapWindows(pWin->drawable.pScreen); + } + + return True; +} + +Bool nxagentSomeWindowsAreMapped() +{ + WindowPtr pWin = WindowTable[0] -> firstChild; + + while (pWin) + { + if ((pWin -> mapped || nxagentIsIconic(pWin)) && + pWin -> drawable.class == InputOutput) + { + return True; + } + + pWin = pWin -> nextSib; + } + + return False; +} + +Bool nxagentDestroyWindow(WindowPtr pWin) +{ + int i; + int j; + + nxagentPrivWindowPtr pWindowPriv; + + if (nxagentScreenTrap == 1) + { + return 1; + } + + nxagentClearClipboard(NULL, pWin); + + for (j = 0; j < nxagentExposeQueue.length; j++) + { + i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE; + + if (nxagentExposeQueue.exposures[i].pWindow == pWin) + { + if (nxagentExposeQueue.exposures[i].localRegion != NullRegion) + { + REGION_DESTROY(pWin -> drawable.pScreen, nxagentExposeQueue.exposures[i].localRegion); + } + + nxagentExposeQueue.exposures[i].localRegion = NullRegion; + + if (nxagentExposeQueue.exposures[i].remoteRegion != NullRegion) + { + REGION_DESTROY(pWin -> drawable.pScreen, nxagentExposeQueue.exposures[i].remoteRegion); + } + + nxagentExposeQueue.exposures[i].remoteRegion = NullRegion; + } + } + + nxagentDeleteConfiguredWindow(pWin); + + pWindowPriv = nxagentWindowPriv(pWin); + + if (pWin->nextSib) + { + nxagentWindowPriv(pWin->nextSib)->siblingAbove = + pWindowPriv->siblingAbove; + } + + #ifdef NXAGENT_SHAPE2 + + #ifdef SHAPE + + if (pWindowPriv->boundingShape) + { + REGION_DESTROY(pWin->drawable.pScreen, + pWindowPriv->boundingShape); + } + + if (pWindowPriv->clipShape) + { + REGION_DESTROY(pWin->drawable.pScreen, + pWindowPriv->clipShape); + } + + #endif + + #else + + REGION_DESTROY(pWin->drawable.pScreen, + pWindowPriv->boundingShape); + + REGION_DESTROY(pWin->drawable.pScreen, + pWindowPriv->clipShape); + + #endif + + if (pWindowPriv -> corruptedRegion) + { + REGION_DESTROY(pWin -> drawable.pScreen, + pWindowPriv -> corruptedRegion); + + pWindowPriv -> corruptedRegion = NULL; + } + + if (nxagentSynchronization.pDrawable == (DrawablePtr) pWin) + { + nxagentSynchronization.pDrawable = NULL; + + #ifdef TEST + fprintf(stderr, "nxagentDestroyWindow: Synchronization drawable [%p] removed from resources.\n", + (void *) pWin); + #endif + } + + nxagentDestroyCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW); + + nxagentDestroyDrawableBitmap((DrawablePtr) pWin); + + if (pWindowPriv -> splitResource != NULL) + { + nxagentReleaseSplit((DrawablePtr) pWin); + } + + XDestroyWindow(nxagentDisplay, nxagentWindow(pWin)); + + if (nxagentOption(Rootless)) + { + nxagentRootlessDelTopLevelWindow(pWin); + } + + nxagentSplashCount--; + + #ifdef DEBUG + fprintf(stderr, "nxagentDestroyWindow: The splash counter is now [%d].\n", + nxagentSplashCount); + #endif + + if (nxagentSplashCount == 1) + { + XClearWindow(nxagentDisplay, nxagentWindowPriv(nxagentRootTileWindow) -> window); + } + + if (pWin == nxagentRootTileWindow) + { + nxagentWindowPriv(nxagentRootTileWindow)->window = None; + + nxagentRootTileWindow = None; + } + + pWindowPriv->window = None; + + if (pWin -> optional) + { + pWin -> optional -> userProps = NULL; + } + + if (nxagentOption(Rootless) && nxagentRootlessDialogPid == 0 && + nxagentLastWindowDestroyed == False && nxagentSomeWindowsAreMapped() == False) + { + #ifdef TEST + fprintf(stderr, "nxagentDestroyWindow: Last mapped window as been destroyed.\n"); + #endif + + nxagentLastWindowDestroyed = True; + nxagentLastWindowDestroyedTime = GetTimeInMillis(); + } + + return True; +} + +Bool nxagentPositionWindow(WindowPtr pWin, int x, int y) +{ + if (nxagentScreenTrap == 1) + { + return True; + } + + #ifdef TEST + fprintf(stderr, "nxagentPositionWindow: Changing position of window [%p][%ld] to [%d,%d].\n", + (void *) pWin, nxagentWindow(pWin), x, y); + #endif + + nxagentAddConfiguredWindow(pWin, CWParent | CWX | CWY | CWWidth | + CWHeight | CWBorderWidth); + + return True; +} + +void nxagentRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) +{ + if (nxagentScreenTrap == 1) + { + return; + } + + nxagentAddConfiguredWindow(pWin, CW_RootlessRestack); + +} + +void nxagentSwitchFullscreen(ScreenPtr pScreen, Bool switchOn) +{ + Window w; + XSetWindowAttributes attributes; + unsigned long valuemask; + + if (nxagentOption(Rootless)) + { + return; + } + + if (!switchOn) + { + nxagentWMDetect(); + + if (!nxagentWMIsRunning) + { + #ifdef WARNING + fprintf(stderr, "Warning: Can't switch to window mode, no window manager has been detected.\n"); + #endif + + return; + } + } + + w = nxagentDefaultWindows[pScreen -> myNum]; + attributes.override_redirect = switchOn; + valuemask = CWOverrideRedirect; + XUnmapWindow(nxagentDisplay, w); + XChangeWindowAttributes(nxagentDisplay, w, valuemask, &attributes); + + if (switchOn) + { + /* + * Change to fullscreen mode. + */ + + struct timeval timeout; + int i; + XEvent e; + + /* + * Wait for window manager reparenting the default window. + */ + + for (i = 0; i < 100 && nxagentWMIsRunning; i++) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchFullscreen: WARNING! Going to wait for the ReparentNotify event.\n"); + #endif + + if (XCheckTypedWindowEvent(nxagentDisplay, w, ReparentNotify, &e)) + { + break; + } + + /* + * This should also flush + * the NX link for us. + */ + + XSync(nxagentDisplay, 0); + + timeout.tv_sec = 0; + timeout.tv_usec = 50 * 1000; + + nxagentWaitEvents(nxagentDisplay, &timeout); + } + + if (i < 100) + { + /* + * The window manager has done with the reparent + * operation. We can resize and map the window. + */ + + nxagentChangeOption(Fullscreen, True); + + /* + * Save the window-mode configuration. + */ + + nxagentChangeOption(SavedX, nxagentOption(X)); + nxagentChangeOption(SavedY, nxagentOption(Y)); + nxagentChangeOption(SavedWidth, nxagentOption(Width)); + nxagentChangeOption(SavedHeight, nxagentOption(Height)); + nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth)); + nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight)); + + /* + * Reconf the Default window. + */ + + nxagentChangeOption(X, 0); + nxagentChangeOption(Y, 0); + nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + + /* + * Move the root window. + */ + + nxagentChangeOption(RootX, (nxagentOption(Width) - nxagentOption(RootWidth)) / 2); + nxagentChangeOption(RootY, (nxagentOption(Height) - nxagentOption(RootHeight)) / 2); + nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth)); + nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight)); + + XMoveResizeWindow(nxagentDisplay, w, nxagentOption(X), nxagentOption(Y), + nxagentOption(Width), nxagentOption(Height)); + + nxagentUpdateViewportFrame(0, 0, nxagentOption(RootWidth), nxagentOption(RootHeight)); + + XMoveWindow(nxagentDisplay, nxagentWindow(WindowTable[pScreen -> myNum]), + nxagentOption(RootX), nxagentOption(RootY)); + + /* + * We disable the screensaver when changing + * mode to fullscreen. Is it really needed? + */ + + XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking); + + if (nxagentIconWindow == None) + { + nxagentIconWindow = nxagentCreateIconWindow(); + + XMapWindow(nxagentDisplay, nxagentIconWindow); + } + + XMapRaised(nxagentDisplay, w); + XSetInputFocus(nxagentDisplay, w, RevertToParent, CurrentTime); + XCheckTypedWindowEvent(nxagentDisplay, w, LeaveNotify, &e); + nxagentFullscreenWindow = w; + + if (nxagentOption(DesktopResize) == 1) + { + if (nxagentOption(Shadow) == 0) + { + nxagentRRSetScreenConfig(pScreen, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), + HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))); + } + else + { + nxagentShadowAdaptToRatio(); + } + } + } + else + { + /* + * We have waited for a reparent event unsuccessfully. + * Something happened to the window manager. + */ + + #ifdef WARNING + fprintf(stderr, "nxagentSwitchFullscreen: WARNING! Expected ReparentNotify event missing.\n"); + #endif + + nxagentWMIsRunning = False; + attributes.override_redirect = False; + XChangeWindowAttributes(nxagentDisplay, w, valuemask, &attributes); + XMapWindow(nxagentDisplay, w); + } + } + else + { + /* + * FIXME: + * It could be necessary: + * - To restore screensaver. + * - To set or reset nxagentForceBackingStore flag. + * - To grab keyboard. + * - To propagate device settings to the X server if no WM is running. + */ + + /* + * Change to windowed mode. + */ + + nxagentChangeOption(Fullscreen, False); + XDestroyWindow(nxagentDisplay, nxagentIconWindow); + nxagentIconWindow = nxagentFullscreenWindow = None; + + if (nxagentOption(DesktopResize) == 1) + { + nxagentChangeOption(RootWidth, nxagentOption(SavedRootWidth)); + nxagentChangeOption(RootHeight, nxagentOption(SavedRootHeight)); + + if (nxagentOption(Shadow) == 0) + { + nxagentRRSetScreenConfig(pScreen, nxagentOption(RootWidth), nxagentOption(RootHeight)); + } + } + + nxagentChangeOption(X, nxagentOption(SavedX)); + nxagentChangeOption(Y, nxagentOption(SavedY)); + nxagentChangeOption(Width, nxagentOption(SavedWidth)); + nxagentChangeOption(Height, nxagentOption(SavedHeight)); + + if (nxagentOption(Shadow) == 1 && nxagentOption(DesktopResize) == 1) + { + nxagentShadowAdaptToRatio(); + } + + XMoveResizeWindow(nxagentDisplay, w, nxagentOption(X), nxagentOption(Y), + nxagentOption(Width), nxagentOption(Height)); + + nxagentUpdateViewportFrame(0, 0, nxagentOption(Width), nxagentOption(Height)); + + XMoveWindow(nxagentDisplay, nxagentWindow(WindowTable[pScreen -> myNum]), 0, 0); + XMapWindow(nxagentDisplay, w); + + nxagentChangeOption(RootX, 0); + nxagentChangeOption(RootY, 0); + } + + XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0, + nxagentOption(Width), nxagentOption(Height)); +} + +#ifdef VIEWPORT_FRAME + +void nxagentUpdateViewportFrame(int x, int y, int w, int h) +{ + /* + * Four virtual windows make a frame around the viewport. We move the frame + * with the viewport together. The areas going into the viewport were covered by + * the frame and become exposed. This make the agent send expose events to his + * clients. + */ + + XID values[3]; + Mask mask; + + /* + * nxagentScreenTrap = True; + */ + + values[2] = Above; + + values[1] = nxagentOption(RootHeight); + + mask = CWX | CWHeight | CWStackMode; + values[0] = x - NXAGENT_FRAME_WIDTH; + ConfigureWindow(nxagentViewportFrameLeft, mask, (XID *) &values, serverClient); + + values[0] = x + w; + ConfigureWindow(nxagentViewportFrameRight, mask, (XID *) &values, serverClient); + + values[1] = nxagentOption(RootWidth); + + mask = CWY | CWWidth | CWStackMode; + values[0] = y - NXAGENT_FRAME_WIDTH; + ConfigureWindow(nxagentViewportFrameAbove, mask, (XID *) &values, serverClient); + + values[0] = y + h; + ConfigureWindow(nxagentViewportFrameBelow, mask, (XID *) &values, serverClient); + + /* + * nxagentScreenTrap = False; + */ +} + +#endif /* #ifdef VIEWPORT_FRAME */ + +void nxagentMoveViewport(ScreenPtr pScreen, int hShift, int vShift) +{ + int newX; + int newY; + int oldX; + int oldY; + + Bool doMove = False; + oldX = 0; + oldY = 0; + + if (nxagentOption(Rootless)) + { + return; + } + + /* + * We must keep x coordinate between viewportXSpan and zero, if viewportXSpan + * is less then zero. If viewportXSpan is greater or equal to zero, it means + * the agent root window has a size smaller than the agent default window. + * In this case we keep the old coordinate. + */ + + #ifdef DEBUG + fprintf(stderr, "nxagentMoveViewport: RootX[%i] RootY[%i], hShift[%i] vShift[%i].\n", + nxagentOption(RootX), nxagentOption(RootY), hShift, vShift); + #endif + + nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth)); + + nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight)); + + if (nxagentOption(ViewportXSpan) < 0) + { + newX = nxagentOption(RootX) - hShift; + + if (newX > 0) + { + newX = 0; + } + else if (newX < nxagentOption(ViewportXSpan)) + { + newX = nxagentOption(ViewportXSpan); + } + } + else if (nxagentOption(ViewportXSpan) == 0) + { + newX = 0; + } + else + { + newX = nxagentOption(RootX); + } + + if (nxagentOption(ViewportYSpan) < 0) + { + newY = nxagentOption(RootY) - vShift; + + if (newY > 0) + { + newY = 0; + } + else if (newY < nxagentOption(ViewportYSpan)) + { + newY = nxagentOption(ViewportYSpan); + } + } + else if (nxagentOption(ViewportYSpan) == 0) + { + newY = 0; + } + else + { + newY = nxagentOption(RootY); + } + + oldX = nxagentOption(RootX); + + if (newX != nxagentOption(RootX)) + { + nxagentChangeOption(RootX, newX); + + doMove = True; + } + + oldY = nxagentOption(RootY); + + if (newY != nxagentOption(RootY)) + { + nxagentChangeOption(RootY, newY); + + doMove = True; + } + + if (doMove) + { + #ifdef TEST + fprintf(stderr, "nxagentMoveViewport: New viewport geometry: (%d, %d)-" + "(%d, %d)\n", -nxagentOption(RootX), -nxagentOption(RootY), + -nxagentOption(RootX) + nxagentOption(Width), + -nxagentOption(RootY) + nxagentOption(Height)); + + fprintf(stderr, "nxagentMoveViewport: Root geometry x=[%d] y=[%d]\n", + WindowTable[pScreen -> myNum] -> drawable.x, + WindowTable[pScreen -> myNum] -> drawable.y ); + #endif + + XMoveWindow(nxagentDisplay, nxagentWindow(WindowTable[pScreen -> myNum]), + nxagentOption(RootX), nxagentOption(RootY)); + + if (nxagentOption(ClientOs) == ClientOsWinnt) + { + /* + * If doMove is True we add exposed rectangles + * to the remote expose region. This is done to + * refresh the areas showed newly in the viewport. + * We create two rectangles, one for horizontal + * pan and one for vertical pan. + */ + + BoxRec hRect; + BoxRec vRect; + + hRect.x1 = -newX; + hRect.y1 = -newY; + + if (hShift < 0) + { + hRect.x2 = -oldX; + hRect.y2 = -newY + nxagentOption(Height); + } + else if (hShift > 0) + { + hRect.x1 = -oldX + nxagentOption(Width); + hRect.x2 = -newX + nxagentOption(Width); + hRect.y2 = -newY + nxagentOption(Height); + } + + #ifdef DEBUG + fprintf(stderr, "nxagentMoveViewport: hRect p1[%i, %i] - p2[%i, %i].\n", hRect.x1, hRect.y1, hRect.x2, hRect.y2); + #endif + + vRect.x1 = -newX; + vRect.y1 = -newY; + + if (vShift < 0) + { + vRect.x2 = -newX + nxagentOption(Width); + vRect.y2 = -oldY; + } + else if (vShift > 0) + { + vRect.y1 = -oldY + nxagentOption(Height); + vRect.x2 = -newX + nxagentOption(Width); + vRect.y2 = -newY + nxagentOption(Height); + } + + #ifdef DEBUG + fprintf(stderr, "nxagentMoveViewport: vRect p1[%i, %i] - p2[%i, %i].\n", vRect.x1, vRect.y1, vRect.x2, vRect.y2); + #endif + + if (oldX != newX && hRect.x1 != hRect.x2 && hRect.y1 != hRect.y2) + { + nxagentAddRectToRemoteExposeRegion(&hRect); + } + + if (oldY != newY && vRect.x1 != vRect.x2 && vRect.y1 != vRect.y2) + { + nxagentAddRectToRemoteExposeRegion(&vRect); + } + } + } + + nxagentUpdateViewportFrame(-nxagentOption(RootX), -nxagentOption(RootY), + nxagentOption(Width), nxagentOption(Height)); +} + +void nxagentConfigureWindow(WindowPtr pWin, unsigned int mask) +{ + unsigned int valuemask; + XWindowChanges values; + + if (nxagentScreenTrap == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: WARNING: Called with the screen trap set.\n"); + #endif + + return; + } + + if (nxagentOption(Rootless) == 1 && + nxagentWindowTopLevel(pWin) == 1) + { + mask &= ~(CWSibling | CWStackMode); + } + else + { + if (mask & CW_RootlessRestack) + { + mask = CWStackingOrder; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: Called with window [%p][%ld] and mask [%x].\n", + (void *) pWin, nxagentWindow(pWin), mask); + #endif + + nxagentMoveCorruptedRegion(pWin, mask); + + valuemask = 0; + + if (mask & CW_Update) + { + mask |= CWX | CWY | CWWidth | CWHeight | CWBorderWidth | CWStackingOrder; + } + + if (mask & CWX) + { + valuemask |= CWX; + + values.x = nxagentWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin); + } + + if (mask & CWY) + { + valuemask |= CWY; + + values.y = nxagentWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin); + } + + if (mask & CWWidth) + { + valuemask |= CWWidth; + + values.width = nxagentWindowPriv(pWin)->width = pWin->drawable.width; + } + + if (mask & CWHeight) + { + valuemask |= CWHeight; + + values.height = nxagentWindowPriv(pWin)->height = pWin->drawable.height; + } + + if (mask & CWBorderWidth) + { + valuemask |= CWBorderWidth; + + values.border_width = nxagentWindowPriv(pWin)->borderWidth = + pWin->borderWidth; + } + + if (mask & CW_Update) + { + valuemask = 0; + } + + if (valuemask) + { + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: Going to configure window [%p][%ld] with mask [%x].\n", + (void *) pWin, nxagentWindow(pWin), valuemask); + #endif + + XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), valuemask, &values); + + MAKE_SYNC_CONFIGURE_WINDOW; + } + + if (mask & CWStackingOrder && + nxagentWindowPriv(pWin)->siblingAbove != nxagentWindowSiblingAbove(pWin)) + { + WindowPtr pSib; + + /* + * Find the top sibling. + */ + + for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib); + + /* + * Configure the top sibling. + */ + + valuemask = CWStackMode; + + values.stack_mode = Above; + + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: Going to configure top sibling [%ld] " + "with mask [%x] and parent [%ld].\n", nxagentWindow(pSib), + valuemask, nxagentWindowParent(pWin)); + #endif + + XConfigureWindow(nxagentDisplay, nxagentWindow(pSib), valuemask, &values); + + MAKE_SYNC_CONFIGURE_WINDOW; + + nxagentWindowPriv(pSib)->siblingAbove = None; + + /* + * Configure the rest of siblings. + */ + + valuemask = CWSibling | CWStackMode; + + values.stack_mode = Below; + + for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib) + { + values.sibling = nxagentWindowSiblingAbove(pSib); + + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: Going to configure other sibling [%ld] " + "with mask [%x] and parent [%ld] below [%ld].\n", nxagentWindow(pSib), + valuemask, nxagentWindowParent(pWin), nxagentWindowSiblingAbove(pSib)); + #endif + + XConfigureWindow(nxagentDisplay, nxagentWindow(pSib), valuemask, &values); + + MAKE_SYNC_CONFIGURE_WINDOW; + + nxagentWindowPriv(pSib)->siblingAbove = nxagentWindowSiblingAbove(pSib); + } + + #ifdef TEST + { + Window root_return; + Window parent_return; + Window *children_return; + unsigned int nchildren_return; + Window *pw; + Status result; + + result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + &root_return, &parent_return, &children_return, &nchildren_return); + + if (result) + { + pw = children_return; + + fprintf(stderr, "nxagentConfigureWindow: Children of the root: "); + while(nchildren_return > 0) + { + pSib = nxagentWindowPtr(children_return[--nchildren_return]); + if (pSib) + { + fprintf(stderr, "%lu ", children_return[nchildren_return]); + } + } + fprintf(stderr, "\n"); + + if (children_return) + { + XFree(children_return); + } + } + else + { + fprintf(stderr, "nxagentConfigureWindow: Failed QueryTree request.\n "); + } + } + #endif + } + + #ifdef NXAGENT_SPLASH + + /* + * This should bring again the splash window + * on top, so why the else clause? Is this + * really needed? + * + * + * else if (mask & CWStackingOrder) + * { + * if (nxagentSplashWindow) + * { + * valuemask = CWStackMode; + * + * values.stack_mode = Above; + * + * #ifdef TEST + * fprintf(stderr, "nxagentConfigureWindow: Going to configure splash window [%ld].\n", + * nxagentSplashWindow); + * #endif + * + * XConfigureWindow(nxagentDisplay, nxagentSplashWindow, valuemask, &values); + * + * MAKE_SYNC_CONFIGURE_WINDOW; + * } + * } + */ + + #endif + + if (mask & CW_RootlessRestack) + { + if (!pWin -> prevSib) + { + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: Raising window [%p][%ld].\n", + (void *) pWin, nxagentWindow(pWin)); + #endif + + XRaiseWindow(nxagentDisplay, nxagentWindow(pWin)); + } + else if (!pWin -> nextSib) + { + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: Lowering window [%p][%ld].\n", + (void *) pWin, nxagentWindow(pWin)); + #endif + + XLowerWindow(nxagentDisplay, nxagentWindow(pWin)); + } + else + { + XlibWindow windowList[2]; + + #ifdef TEST + fprintf(stderr, "nxagentConfigureWindow: Putting window [%p][%ld] in the middle.\n", + (void *) pWin, nxagentWindow(pWin)); + #endif + + windowList[0] = nxagentWindow(pWin->prevSib); + windowList[1] = nxagentWindow(pWin); + + XRestackWindows(nxagentDisplay, windowList, 2); + } + } + + #ifdef SHAPE + + if (mask & CW_Shape) + { + nxagentShapeWindow(pWin); + } + + #endif + + if (mask & CW_Map && + (!nxagentOption(Rootless) || + nxagentRootlessWindow != pWin)) + { + XMapWindow(nxagentDisplay, nxagentWindow(pWin)); + + return; + } +} + +void nxagentReparentWindow(pWin, pOldParent) + WindowPtr pWin; + WindowPtr pOldParent; +{ + if (nxagentScreenTrap) + { + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentReparentWindow: window at %p [%lx] previous parent at %p [%lx].\n", + (void*)pWin, nxagentWindow(pWin), + (void*)pOldParent, nxagentWindow(pOldParent)); + #endif + + XReparentWindow(nxagentDisplay, nxagentWindow(pWin), + nxagentWindowParent(pWin), + pWin->origin.x - wBorderWidth(pWin), + pWin->origin.y - wBorderWidth(pWin)); +} + +Bool nxagentChangeWindowAttributes(pWin, mask) + WindowPtr pWin; + unsigned long mask; +{ + XSetWindowAttributes attributes; + + #ifdef TEST + fprintf(stderr, "nxagentChangeWindowAttributes: Changing attributes for window at [%p] with mask [%lu].\n", + (void *) pWin, mask); + #endif + + if (nxagentScreenTrap) + { + return True; + } + + if (mask & CWBackPixmap) + { + switch (pWin->backgroundState) + { + case None: + { + attributes.background_pixmap = None; + attributes.background_pixel = nxagentWhitePixel; + + /* + * One of problems faced during the implementation of lazy + * encoding policies was due to the presence of windows with + * transparent background, usually created by X clients to + * cover some sensible areas (i.e. checkboxes used by + * Konqueror 3.5). The sequence of operations consists in + * drawing the underneath part before covering it with the + * transparent window, so when we synchronize the deferred + * drawing operation we have to bear in mind that the dest- + * ination area is covered by a window. By using the Inclu- + * deInferiors GC's property and by clipping the region to + * synchronize to the borderClip instead of clipList (to + * include the areas covered by children) we can easily take + * care of this situation, but there is a drawback: if the + * children are not transparent, we are going to synchronize + * invisible areas. To avoid this we have added the 'has- + * TransparentChildren' flag, which is set when a window has + * at least one child with background None. The problem is + * that we don't know when to reset the flag. This solution, + * also, doesn't take care of transparent windows which don't + * have childhood relationships with underneath windows. + * We tried to mark the whole windows as dirty when they are + * created to force the synchronization of transparent windows + * with the content of underneath windows, but, of course, + * this works only with the first synchronization because the + * transparent windows will be never marked again as dirty. + */ + + if (pWin -> parent != NULL) + { + nxagentWindowPriv(pWin -> parent) -> hasTransparentChildren = 1; + + #ifdef DEBUG + fprintf(stderr, "nxagentChangeWindowAttributes: WARNING! Window at [%p] got the " + "hasTransparentChildren flag.\n", (void *) pWin); + #endif + } + + break; + } + case ParentRelative: + { + attributes.background_pixmap = ParentRelative; + + break; + } + case BackgroundPixmap: + { + /* + * If a window background is corrupted, we grant + * its usability by clearing it with a solid co- + * lor. When the pixmap will be fully synchroni- + * zed, an expose will be sent to the window's + * hierarchy. + */ + + if (nxagentDrawableStatus((DrawablePtr) pWin -> background.pixmap) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentChangeWindowAttributes: The window at [%p] has the background at [%p] " + "not synchronized.\n", (void *) pWin, (void *) pWin -> background.pixmap); + #endif + + if (nxagentIsCorruptedBackground(pWin -> background.pixmap) == 0) + { + nxagentIsCorruptedBackground(pWin -> background.pixmap) = 1; + + nxagentAllocateCorruptedResource((DrawablePtr) pWin -> background.pixmap, RT_NX_CORR_BACKGROUND); + + /* + * Clearing the remote background to + * make it usable. + */ + + nxagentFillRemoteRegion((DrawablePtr) pWin -> background.pixmap, + nxagentCorruptedRegion((DrawablePtr) pWin -> background.pixmap)); + } + } + + attributes.background_pixmap = nxagentPixmap(pWin -> background.pixmap); + + break; + } + case BackgroundPixel: + { + mask &= ~CWBackPixmap; + + break; + } + } + } + + if (mask & CWBackPixel) + { + if (pWin -> backgroundState == BackgroundPixel) + { + attributes.background_pixel = nxagentPixel(pWin -> background.pixel); + } + else + { + mask &= ~CWBackPixel; + } + } + + if (mask & CWBorderPixmap) + { + if (pWin -> borderIsPixel != 0) + { + mask &= ~CWBorderPixmap; + } + else + { + attributes.border_pixmap = nxagentPixmap(pWin -> border.pixmap); + } + } + + if (mask & CWBorderPixel) + { + if (pWin -> borderIsPixel != 0) + { + attributes.border_pixel = nxagentPixel(pWin -> border.pixel); + } + else + { + mask &= ~CWBorderPixel; + } + } + + if (mask & CWBitGravity) + { + attributes.bit_gravity = pWin -> bitGravity; + } + + /* + * As we set this bit, whe must change dix in + * order not to perform PositionWindow and let + * X move children windows for us. + */ + + if (mask & CWWinGravity) + { + attributes.win_gravity = pWin -> winGravity; + } + +/* +FIXME: Do we need to set the attribute on the + remote display? +*/ + if (mask & CWBackingStore) + { + attributes.backing_store = pWin -> backingStore; + + #ifdef TEST + fprintf(stderr, "nxagentChangeWindowAttributes: Changing backing store value to %d" + " for window at %p.\n", pWin -> backingStore, (void*)pWin); + #endif + } + + if (mask & CWBackingPlanes) + { + if ((nxagentBackingStore == NotUseful) || (pWin -> optional == NULL)) + { + mask &= ~CWBackingPlanes; + } + else + { + attributes.backing_planes = pWin -> optional -> backingBitPlanes; + } + } + + if (mask & CWBackingPixel) + { + if ((nxagentBackingStore == NotUseful) || (pWin -> optional == NULL)) + { + mask &= ~CWBackingPixel; + } + else + { + attributes.backing_pixel = pWin -> optional -> backingPixel; + } + } + + if (mask & CWOverrideRedirect) + { + attributes.override_redirect = pWin -> overrideRedirect; + } + +/* +FIXME: Do we need to set the attribute on the + remote display? +*/ + if (mask & CWSaveUnder) + { + attributes.save_under = pWin -> saveUnder; + } + + /* + * Events are handled elsewhere. + */ + + if (mask & CWEventMask) + { + mask &= ~CWEventMask; + } + + if (mask & CWDontPropagate) + { + mask &= ~CWDontPropagate; + } + + if (mask & CWColormap) + { + ColormapPtr pCmap; + + pCmap = (ColormapPtr) LookupIDByType(wColormap(pWin), RT_COLORMAP); + +/* +FIXME: When the caller is nxagentReconfigureWindow + sometimes wColormap(pWin) is 0. Could a window + have no colormap? +*/ + if (pCmap != NULL) + { + attributes.colormap = nxagentColormap(pCmap); + + nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentChangeWindowAttributes: WARNING! Bad colormap " + "[%lu] for window at [%p].\n", wColormap(pWin), (void *) pWin); + #endif + + mask &= ~CWColormap; + } + } + + if (mask & CWCursor) + { + if (nxagentOption(Rootless)) + { + if (pWin->cursorIsNone == 0 && pWin->optional != NULL && + pWin->optional->cursor != NULL && nxagentCursorPriv(pWin -> + optional -> cursor, pWin -> drawable.pScreen) != NULL) + { + attributes.cursor = nxagentCursor(pWin -> optional -> cursor, + pWin -> drawable.pScreen); + } + else + { + attributes.cursor = None; + } + } + else + { + /* + * This is handled in cursor code + */ + + mask &= ~CWCursor; + } + } + + if (mask != 0) + { + XChangeWindowAttributes(nxagentDisplay, nxagentWindow(pWin), mask, &attributes); + } + + return 1; +} + +Bool nxagentRealizeWindow(WindowPtr pWin) +{ + if (nxagentScreenTrap == 1) + { + return True; + } + + /* + * Not needed. + * + * nxagentConfigureWindow(pWin, CWStackingOrder); + * + * nxagentFlushConfigureWindow(); + */ + + nxagentAddConfiguredWindow(pWin, CWStackingOrder); + nxagentAddConfiguredWindow(pWin, CW_Shape); + + #ifdef SHAPE + + /* + * Not needed. + * + * nxagentShapeWindow(pWin); + */ + + #endif /* SHAPE */ + + /* + * Mapping of the root window is called by + * InitRootWindow in DIX. Skip the operation + * if we are in rootless mode. + */ + + /* + * if (!nxagentOption(Rootless) || + * nxagentRootlessWindow != pWin) + * { + * XMapWindow(nxagentDisplay, nxagentWindow(pWin)); + * } + */ + + #ifdef TEST + if (nxagentOption(Rootless) && nxagentLastWindowDestroyed) + { + fprintf(stderr, "nxagentRealizeWindow: Window realized. Stopped termination for rootless session.\n"); + } + #endif + + nxagentAddConfiguredWindow(pWin, CW_Map); + + nxagentLastWindowDestroyed = False; + + return True; +} + +Bool nxagentUnrealizeWindow(pWin) + WindowPtr pWin; +{ + if (nxagentScreenTrap) + { + return True; + } + + XUnmapWindow(nxagentDisplay, nxagentWindow(pWin)); + + return True; +} + +void nxagentFrameBufferPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + + void *PaintWindowBackgroundBackup; + + if (pWin->backgroundState == BackgroundPixmap) + { + pWin->background.pixmap = nxagentVirtualPixmap(pWin->background.pixmap); + } + + if (pWin->borderIsPixel == False) + { + pWin->border.pixmap = nxagentVirtualPixmap(pWin->border.pixmap); + } + + PaintWindowBackgroundBackup = pWin->drawable.pScreen -> PaintWindowBackground; + + pWin->drawable.pScreen -> PaintWindowBackground = nxagentFrameBufferPaintWindow; + + fbPaintWindow(pWin, pRegion, what); + + pWin->drawable.pScreen -> PaintWindowBackground = PaintWindowBackgroundBackup; + + if (pWin->backgroundState == BackgroundPixmap) + { + pWin->background.pixmap = nxagentRealPixmap(pWin->background.pixmap); + } + + if (pWin->borderIsPixel == False) + { + pWin->border.pixmap = nxagentRealPixmap(pWin->border.pixmap); + } +} + +void nxagentPaintWindowBackground(pWin, pRegion, what) + WindowPtr pWin; + RegionPtr pRegion; + int what; +{ + int i; + + RegionRec temp; + + if (pWin -> realized) + { + BoxPtr pBox; + + pBox = REGION_RECTS(pRegion); + + for (i = 0; i < REGION_NUM_RECTS(pRegion); i++) + { + XClearArea(nxagentDisplay, nxagentWindow(pWin), + pBox[i].x1 - pWin->drawable.x, + pBox[i].y1 - pWin->drawable.y, + pBox[i].x2 - pBox[i].x1, + pBox[i].y2 - pBox[i].y1, + False); + } + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentPaintWindowBackground: Saving the operation with window " + "at [%p] not realized.\n", (void *) pWin); + } + #endif + + /* + * The framebuffer operations don't take care of + * clipping to the actual area of the framebuffer + * so we need to clip ourselves. + */ + + REGION_INIT(pWin -> drawable.pScreen, &temp, NullBox, 1); + + REGION_INTERSECT(pWin -> drawable.pScreen, &temp, pRegion, &pWin -> clipList); + + nxagentFrameBufferPaintWindow(pWin, &temp, what); + + REGION_UNINIT(pWin -> drawable.pScreen, &temp); +} + +void nxagentPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what) +{ + RegionRec temp; + + /* + * The framebuffer operations don't take care of + * clipping to the actual area of the framebuffer + * so we need to clip ourselves. + */ + + REGION_INIT(pWin -> drawable.pScreen, &temp, NullBox, 1); + + REGION_INTERSECT(pWin -> drawable.pScreen, &temp, pRegion, &pWin -> borderClip); + + nxagentFrameBufferPaintWindow(pWin, &temp, what); + + REGION_UNINIT(pWin -> drawable.pScreen, &temp); +} + +void nxagentCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion) +{ + fbCopyWindow(pWin, oldOrigin, oldRegion); +} + +void nxagentClipNotify(WindowPtr pWin, int dx, int dy) +{ + /* + * nxagentConfigureWindow(pWin, CWStackingOrder); + */ + + nxagentAddConfiguredWindow(pWin, CWStackingOrder); + nxagentAddConfiguredWindow(pWin, CW_Shape); + +#ifdef NXAGENT_SHAPE + return; +#else + +#ifdef SHAPE + +/* + * nxagentShapeWindow(pWin); + */ + +#endif /* SHAPE */ + +#endif /* NXAGENT_SHAPE */ +} + +void nxagentWindowExposures(WindowPtr pWin, RegionPtr pRgn, RegionPtr other_exposed) +{ + /* + * The problem: we want to synthetize the expose events internally, so + * that we reduce the time between a window operation and the corresp- + * onding graphical output, but at the same time we need to take care + * of the remote exposures, as we need to handle those cases where our + * windows are covered by the windows on the real display. Handling + * both the local and the remote exposures we would generate the same + * redraws twice, something we call "double refreshes", so we must be + * able to identify which events have been already sent to our clients. + * + * Here is how the algorithm is working: + * + * - We collect the exposures that the agent sent to its clients in a + * region (the "local-region") and store the region for a given win- + * dow in a vector. + * + * - Another region collects the expose that were received from the + * real X server (the "remote-region") for the same window. + * + * - We create a "fake" off-screen window. For every generated region + * we send a ConfigureWindow request for that window to synchronize + * ourselves with both the remote X server and/or the window manager. + * + * - When the ConfigureNotify is received, we calculate the difference + * between the "remote-region" and the "local-region" for the window + * that had collected exposures. + * + * - Finally we send the resulting exposures to our clients. + * + * As you may have guessed, the windows are synchronized per-region, + * that is there is a single region for a set of exposures. The regions + * are handled in order. This means that we can always calculate the + * final region by referring to the first element of the vector. + */ + + RegionRec temp; + BoxRec box; + + if (nxagentSessionState != SESSION_DOWN) + { + if (nxagentExposeArrayIsInitialized == 0) + { + int i; + + XSetWindowAttributes attributes; + + #ifdef TEST + fprintf(stderr, "nxagentWindowExposures: Initializing expose queue.\n"); + #endif + + attributes.event_mask = StructureNotifyMask; + + for (i = 0; i < EXPOSED_SIZE; i++) + { + nxagentExposeQueue.exposures[i].pWindow = NULL; + nxagentExposeQueue.exposures[i].localRegion = NullRegion; + nxagentExposeQueue.exposures[i].remoteRegion = NullRegion; + nxagentExposeQueue.exposures[i].remoteRegionIsCompleted = False; + nxagentExposeQueue.exposures[i].serial = 0; + } + + nxagentExposeQueue.length = 0; + + nxagentExposeSerial = 0; + + nxagentExposeQueue.start = 0; + + nxagentConfiguredSynchroWindow = XCreateWindow(nxagentDisplay, DefaultRootWindow(nxagentDisplay), 0, 0, + 1, 1, 0, 0, InputOutput, 0, CWEventMask, &attributes); + + nxagentInitRemoteExposeRegion(); + + nxagentExposeArrayIsInitialized = 1; + } + + REGION_INIT(pWin -> drawable.pScreen, &temp, (BoxRec *) NULL, 1); + + if (pRgn != NULL) + { + if (REGION_NUM_RECTS(pRgn) > RECTLIMIT) + { + box = *REGION_EXTENTS(pWin -> drawable.pScreen, pRgn); + + REGION_EMPTY(pWin -> drawable.pScreen, pRgn); + REGION_INIT(pWin -> drawable.pScreen, pRgn, &box, 1); + } + + REGION_UNION(pWin -> drawable.pScreen, &temp, &temp, pRgn); + } + + if (other_exposed != NULL) + { + REGION_UNION(pWin -> drawable.pScreen, &temp, &temp, other_exposed); + } + + if (REGION_NIL(&temp) == 0) + { + REGION_TRANSLATE(pWin -> drawable.pScreen, &temp, + -(pWin -> drawable.x), -(pWin -> drawable.y)); + + if (nxagentExposeQueue.length < EXPOSED_SIZE) + { + XWindowChanges changes; + int index; + + index = (nxagentExposeQueue.start + nxagentExposeQueue.length) % EXPOSED_SIZE; + + nxagentExposeQueue.exposures[index].pWindow = pWin; + + nxagentExposeQueue.exposures[index].localRegion = REGION_CREATE(pwin -> drawable.pScreen, NULL, 1); + + if (nxagentOption(Rootless) && nxagentWindowPriv(pWin) && + (nxagentWindowPriv(pWin) -> isMapped == 0 || + nxagentWindowPriv(pWin) -> visibilityState != VisibilityUnobscured)) + { + nxagentExposeQueue.exposures[index].remoteRegion = REGION_CREATE(pwin -> drawable.pScreen, NULL, 1); + + REGION_UNION(pWin -> drawable.pScreen, nxagentExposeQueue.exposures[index].remoteRegion, + nxagentExposeQueue.exposures[index].remoteRegion, &temp); + + #ifdef TEST + fprintf(stderr, "nxagentWindowExposures: Added region to remoteRegion for window [%ld] to position [%d].\n", + nxagentWindow(pWin), nxagentExposeQueue.length); + #endif + } + else + { + REGION_UNION(pWin -> drawable.pScreen, nxagentExposeQueue.exposures[index].localRegion, + nxagentExposeQueue.exposures[index].localRegion, &temp); + + #ifdef TEST + fprintf(stderr, "nxagentWindowExposures: Added region to localRegion for window [%ld] to position [%d].\n", + nxagentWindow(pWin), nxagentExposeQueue.length); + #endif + } + + nxagentExposeSerial = (nxagentExposeSerial - 1) % EXPOSED_SIZE; + + changes.x = nxagentExposeSerial; + changes.y = -2; + + nxagentExposeQueue.exposures[index].serial = nxagentExposeSerial; + + #ifdef TEST + fprintf(stderr, "nxagentWindowExposures: Added region to queue with serial [%d].\n", nxagentExposeSerial); + #endif + + /* + * Mark this region for sending a synchro, + * in nxagentFlushConfigureWindow(). + */ + + nxagentExposeQueue.exposures[index].synchronize = 1; + + nxagentExposeQueue.length++; + + if (nxagentOption(Rootless) && nxagentWindowPriv(pWin) && + (nxagentWindowPriv(pWin) -> isMapped == 0 || + nxagentWindowPriv(pWin) -> visibilityState != VisibilityUnobscured)) + { + REGION_UNINIT(pWin -> drawable.pScreen, &temp); + + return; + } + } + else + { + REGION_UNINIT(pWin -> drawable.pScreen, &temp); + + #ifdef TEST + fprintf(stderr, "nxagentWindowExposures: WARNING! Reached maximum size of collect exposures vector.\n"); + #endif + + if ((pRgn != NULL && REGION_NOTEMPTY(pWin -> drawable.pScreen, pRgn) != 0) || + (other_exposed != NULL && REGION_NOTEMPTY(pWin -> drawable.pScreen, other_exposed) != 0)) + { + nxagentUnmarkExposedRegion(pWin, pRgn, other_exposed); + + miWindowExposures(pWin, pRgn, other_exposed); + } + + return; + } + } + + REGION_UNINIT(pWin -> drawable.pScreen, &temp); + } + + if ((pRgn != NULL && REGION_NOTEMPTY(pWin -> drawable.pScreen, pRgn) != 0) || + (other_exposed != NULL && REGION_NOTEMPTY(pWin -> drawable.pScreen, other_exposed) != 0)) + { + nxagentUnmarkExposedRegion(pWin, pRgn, other_exposed); + + miWindowExposures(pWin, pRgn, other_exposed); + } + + return; +} + +#ifdef SHAPE +static Bool nxagentRegionEqual(RegionPtr pReg1, RegionPtr pReg2) +{ + BoxPtr pBox1, pBox2; + unsigned int n1, n2; + + if (pReg1 == pReg2) return True; + + if (pReg1 == NullRegion || pReg2 == NullRegion) return False; + + pBox1 = REGION_RECTS(pReg1); + n1 = REGION_NUM_RECTS(pReg1); + + pBox2 = REGION_RECTS(pReg2); + n2 = REGION_NUM_RECTS(pReg2); + + if (n1 != n2) return False; + + if (pBox1 == pBox2) return True; + + if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec))) return False; + + return True; +} + +void nxagentShapeWindow(WindowPtr pWin) +{ + Region reg; + BoxPtr pBox; + XRectangle rect; + int i; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentShapeWindow: Window at [%p][%ld].\n", + (void *) pWin, nxagentWindow(pWin)); + #endif + + if (!nxagentRegionEqual(nxagentWindowPriv(pWin)->boundingShape, + wBoundingShape(pWin))) + { + #ifdef DEBUG + fprintf(stderr, "nxagentShapeWindow: Bounding shape differs.\n"); + #endif + + if (wBoundingShape(pWin)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentShapeWindow: wBounding shape has [%ld] rects.\n", + REGION_NUM_RECTS(wBoundingShape(pWin))); + #endif + +#ifdef NXAGENT_SHAPE2 + if (!nxagentWindowPriv(pWin)->boundingShape) + { + nxagentWindowPriv(pWin)->boundingShape = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); + } +#endif + + REGION_COPY(pWin->drawable.pScreen, + nxagentWindowPriv(pWin)->boundingShape, wBoundingShape(pWin)); + + reg = XCreateRegion(); + pBox = REGION_RECTS(nxagentWindowPriv(pWin)->boundingShape); + for (i = 0; + i < REGION_NUM_RECTS(nxagentWindowPriv(pWin)->boundingShape); + i++) + { + rect.x = pBox[i].x1; + rect.y = pBox[i].y1; + rect.width = pBox[i].x2 - pBox[i].x1; + rect.height = pBox[i].y2 - pBox[i].y1; + XUnionRectWithRegion(&rect, reg, reg); + } + +#ifndef NXAGENT_SHAPE + XShapeCombineRegion(nxagentDisplay, nxagentWindow(pWin), + ShapeBounding, 0, 0, reg, ShapeSet); +#endif + + XDestroyRegion(reg); + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentShapeWindow: wBounding shape does not exist. Removing the shape.\n"); + #endif + + REGION_EMPTY(pWin->drawable.pScreen, + nxagentWindowPriv(pWin)->boundingShape); + +#ifndef NXAGENT_SHAPE + XShapeCombineMask(nxagentDisplay, nxagentWindow(pWin), + ShapeBounding, 0, 0, None, ShapeSet); +#endif + + } + } + + if (!nxagentRegionEqual(nxagentWindowPriv(pWin)->clipShape, wClipShape(pWin))) + { + #ifdef DEBUG + fprintf(stderr, "nxagentShapeWindow: Clip shape differs.\n"); + #endif + + if (wClipShape(pWin)) + { + #ifdef DEBUG + fprintf(stderr, "nxagentShapeWindow: wClip shape has [%ld] rects.\n", + REGION_NUM_RECTS(wClipShape(pWin))); + #endif + +#ifdef NXAGENT_SHAPE2 + if (!nxagentWindowPriv(pWin)->clipShape) + { + nxagentWindowPriv(pWin)->clipShape = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); + } +#endif + + REGION_COPY(pWin->drawable.pScreen, + nxagentWindowPriv(pWin)->clipShape, wClipShape(pWin)); + + reg = XCreateRegion(); + pBox = REGION_RECTS(nxagentWindowPriv(pWin)->clipShape); + for (i = 0; + i < REGION_NUM_RECTS(nxagentWindowPriv(pWin)->clipShape); + i++) + { + rect.x = pBox[i].x1; + rect.y = pBox[i].y1; + rect.width = pBox[i].x2 - pBox[i].x1; + rect.height = pBox[i].y2 - pBox[i].y1; + XUnionRectWithRegion(&rect, reg, reg); + } + +#ifndef NXAGENT_SHAPE + XShapeCombineRegion(nxagentDisplay, nxagentWindow(pWin), + ShapeClip, 0, 0, reg, ShapeSet); +#endif + + XDestroyRegion(reg); + } + else + { + #ifdef DEBUG + fprintf(stderr, "nxagentShapeWindow: wClip shape does not exist. Removing the shape.\n"); + #endif + + REGION_EMPTY(pWin->drawable.pScreen, + nxagentWindowPriv(pWin)->clipShape); + +#ifndef NXAGENT_SHAPE + XShapeCombineMask(nxagentDisplay, nxagentWindow(pWin), + ShapeClip, 0, 0, None, ShapeSet); +#endif + } + } +} +#endif /* SHAPE */ + +static int nxagentForceExposure(WindowPtr pWin, pointer ptr) +{ + RegionPtr exposedRgn; + BoxRec Box; + WindowPtr pRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + if (pWin -> drawable.class != InputOnly) + { + Box.x1 = pWin->drawable.x; + Box.y1 = pWin->drawable.y; + Box.x2 = Box.x1 + pWin->drawable.width; + Box.y2 = Box.y1 + pWin->drawable.height; + + exposedRgn = REGION_CREATE(pWin->drawable.pScreen, &Box, 1); + REGION_INTERSECT(pWin->drawable.pScreen, exposedRgn, exposedRgn, &pRoot->winSize); + + if (exposedRgn != NULL && REGION_NOTEMPTY(pWin -> drawable.pScreen, exposedRgn) != 0) + { + miWindowExposures(pWin, exposedRgn, NullRegion); + } + + REGION_DESTROY(pWin->drawable.pScreen, exposedRgn); + } + + return WT_WALKCHILDREN; +} + +void nxagentRefreshWindows(WindowPtr pWin) +{ + int action = 1; + + TraverseTree(pWin, nxagentForceExposure, &action); +} + +void nxagentUnmapWindows(void) +{ + int i; + + if (nxagentOption(Fullscreen) == 1) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + if (nxagentDefaultWindows[i]) + { + XUnmapWindow(nxagentDisplay, nxagentDefaultWindows[i]); + } + } + } + + NXFlushDisplay(nxagentDisplay, NXFlushLink); +} + +void nxagentMapDefaultWindows() +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) + { + WindowPtr pWin = WindowTable[i]; + + ScreenPtr pScreen = pWin -> drawable.pScreen; + + MapWindow(pWin, serverClient); + + if (nxagentOption(Rootless) == 0) + { + /* + * Show the NX splash screen. + */ + + #ifdef TEST + fprintf(stderr, "nxagentMapDefaultWindows: Showing the splash window.\n"); + #endif + + nxagentShowSplashWindow(nxagentDefaultWindows[pScreen->myNum]); + + /* + * Map the default window. Defer the mapping if the session is + * of shadow type. If no WM is running on the remote display, + * map the window soon anyway: this avoids a flickering effect + * on the !M logo if the shadow session is displayed from a + * Windows client. + */ + + if (nxagentOption(Shadow) == 0 || nxagentWMIsRunning == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentMapDefaultWindows: Mapping default window id [%ld].\n", + nxagentDefaultWindows[pScreen->myNum]); + #endif + + XMapWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum]); + } + + /* + * Map and raise the input window. + */ + + XMapWindow(nxagentDisplay, nxagentInputWindows[pScreen->myNum]); + + /* + * At reconnection the Input Window is + * raised in nxagentReconnectAllWindows, + * after the Root Window is mapped. + */ + + if (nxagentReconnectTrap == 0) + { + XRaiseWindow(nxagentDisplay, nxagentInputWindows[pScreen->myNum]); + } + } + + /* + * Send a SetSelectionOwner request + * to notify of the agent start. + */ + + XSetSelectionOwner(nxagentDisplay, serverCutProperty, + nxagentDefaultWindows[i], CurrentTime); + } + + /* + * Map the icon window. + */ + + if (nxagentIconWindow != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentMapDefaultWindows: Mapping icon window id [%ld].\n", + nxagentIconWindow); + #endif + + XMapWindow(nxagentDisplay, nxagentIconWindow); + + if (nxagentIpaq != 0) + { + XIconifyWindow(nxagentDisplay, nxagentIconWindow, + DefaultScreen(nxagentDisplay)); + } + } + + /* + * Ensure that the fullscreen window gets the focus. + */ + + if (nxagentFullscreenWindow != 0) + { + XSetInputFocus(nxagentDisplay, nxagentFullscreenWindow, + RevertToParent, CurrentTime); + } + + #ifdef TEST + fprintf(stderr, "nxagentMapDefaultWindows: Completed mapping of default windows.\n"); + #endif +} + +Bool nxagentDisconnectAllWindows(void) +{ + Bool succeded = True; + int i; + WindowPtr pWin; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG) + fprintf(stderr, "nxagentDisconnectAllWindows\n"); + #endif + + for (i = 0; i < screenInfo.numScreens; i++) + { + pWin = WindowTable[i]; + nxagentTraverseWindow( pWin, nxagentDisconnectWindow, &succeded); + nxagentDefaultWindows[i] = None; + } + + #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG + fprintf(stderr, "nxagentDisconnectAllWindows: all windows disconnected\n"); + #endif + + return succeded; +} + +/* + * FIXME: We are giving up reconnecting those pointer + * that are not resource, and we are just disconnecting them. + * perhaps we could do better and reconnect them. + */ + +void nxagentDisconnectWindow(pointer p0, XID x1, pointer p2) +{ + WindowPtr pWin = (WindowPtr)p0; + Bool* pBool = (Bool*)p2; + CursorPtr pCursor = wCursor(pWin); + ScreenPtr pScreen = pWin -> drawable.pScreen; + + if ((pCursor = wCursor(pWin)) && + nxagentCursorPriv(pCursor, pScreen) && + nxagentCursor(pCursor, pScreen)) + { + #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG_disabled + char msg[] = "nxagentDisconnectWindow:"; + + nxagentPrintCursorInfo(pCursor, msg); + #endif + + #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG + fprintf(stderr, "nxagentDisconnectWindow: window %p - disconnecting cursor %p ID %lx\n", + pWin, pCursor, nxagentCursor(pCursor, pScreen)); + #endif + + nxagentDisconnectCursor(pCursor, (XID)0, pBool); + + if (*pBool == False) + { + #ifdef WARNING + fprintf(stderr, "nxagentDisconnectWindow: WARNING failed disconnection of cursor at [%p]" + " for window at [%p]: ignoring it.\n", (void*)pCursor, (void*)pWin); + #endif + + *pBool = True; + } + } + #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG + else if (pCursor) + { + fprintf(stderr, "nxagentDisconnectWindow: window %p - cursor %p already disconnected\n", + pWin, pCursor); + } + #endif + + nxagentWindow(pWin) = None; + + if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized) + { + nxagentDestroyCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW); + } +} + +Bool nxagentReconnectAllWindows(void *p0) +{ + int flexibility = *(int *) p0; + + flexibility = flexibility; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG) + fprintf(stderr, "nxagentReconnectAllWindows\n"); + #endif + + if (WindowTable[0] -> backgroundState == BackgroundPixmap && + WindowTable[0] -> background.pixmap == NULL) + { + FatalError("nxagentReconnectAllWindows: correct the FIXME\n"); + } + + if (nxagentOption(Fullscreen)) + { + WindowTable[0] -> origin.x = nxagentOption(RootX); + WindowTable[0] -> origin.y = nxagentOption(RootY); + } + + if (!nxagentLoopOverWindows(nxagentReconnectWindow)) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectAllWindows: couldn't recreate windows\n"); + #endif + + return False; + } + + #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG + XSync(nxagentDisplay, 0); + fprintf(stderr, "nxagentReconnectAllWindows: all windows recreated\n"); + #endif + + if (!nxagentLoopOverWindows(nxagentReconfigureWindow)) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectAllWindows: couldn't reconfigure windows\n"); + #endif + + return False; + } + + /* + * After the Root Window has + * been mapped, the Input + * Windows is raised. + */ + + if (nxagentOption(Rootless) == 0) + { + int i; + + for (i = 0; i < screenInfo.numScreens; i++) + { + XRaiseWindow(nxagentDisplay, nxagentInputWindows[i]); + } + } + + nxagentFlushConfigureWindow(); + + if (nxagentOption(Fullscreen)) + { + WindowTable[0] -> origin.x = 0; + WindowTable[0] -> origin.y = 0; + } + + #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG + + XSync(nxagentDisplay, 0); + + fprintf(stderr, "nxagentReconnectAllWindows: All windows reconfigured.\n"); + + #endif + + if (nxagentInitClipboard(WindowTable[0]) == -1) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectAllWindows: WARNING! Couldn't initialize the clipboard.\n"); + #endif + + return False; + } + + #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG + + XSync(nxagentDisplay, 0); + + fprintf(stderr, "nxagentReconnectAllWindows: Clipboard initialized.\n"); + + #endif + + #ifdef VIEWPORT_FRAME + + /* + * We move the viewport frames out of the way on the X server side. + */ + + if (nxagentViewportFrameLeft && + nxagentViewportFrameRight && + nxagentViewportFrameAbove && + nxagentViewportFrameBelow) + { + XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameLeft), + -NXAGENT_FRAME_WIDTH, 0); + XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameRight), + nxagentOption(RootWidth), 0); + XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameAbove), + 0, -NXAGENT_FRAME_WIDTH); + XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameBelow), + 0, nxagentOption(RootHeight)); + } + + #endif /* #ifdef VIEWPORT_FRAME */ + + return True; +} + +Bool nxagentSetWindowCursors(void *p0) +{ + int flexibility = *(int *) p0; + + flexibility = flexibility; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG) + fprintf(stderr, "nxagentSetWindowCursors: Going to loop over the windows.\n"); + #endif + + if (!nxagentLoopOverWindows(nxagentReconfigureWindowCursor)) + { + #ifdef WARNING + fprintf(stderr, "nxagentSetWindowCursors: WARNING! Couldn't configure all windows' cursors.\n"); + #endif + + return False; + } + + #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG + fprintf(stderr, "nxagentLoopOverWindows: All cursors configured.\n"); + #endif + + nxagentReDisplayCurrentCursor(); + + return True; +} + +static void nxagentTraverseWindow( + WindowPtr pWin, + void (*pF)(pointer, XID, pointer), + pointer p) +{ + pF(pWin, 0, p); + + if (pWin -> nextSib) + { + nxagentTraverseWindow(pWin -> nextSib, pF, p); + } + + if (pWin -> firstChild) + { + nxagentTraverseWindow(pWin -> firstChild, pF, p); + } +} + +static Bool nxagentLoopOverWindows(void (*pF)(pointer, XID, pointer)) +{ + int i; + Bool windowSuccess = True; + WindowPtr pWin; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pWin = WindowTable[i]; + nxagentTraverseWindow(pWin, pF, &windowSuccess); + } + + return windowSuccess; +} + +static void nxagentReconnectWindow(pointer param0, XID param1, pointer data_buffer) +{ + WindowPtr pWin = (WindowPtr)param0; + Bool *pBool = (Bool*)data_buffer; + Visual *visual; + unsigned long mask; + XSetWindowAttributes attributes; + ColormapPtr pCmap; + + if (!pWin || !*pBool) + return; + + #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG + fprintf(stderr, "nxagentReconnectWindow: %p - ID %lx\n", pWin, nxagentWindow(pWin)); + #endif + + if (pWin->drawable.class == InputOnly) { + mask = CWEventMask; + visual = CopyFromParent; + } + else { + mask = CWEventMask | CWBackingStore; + + attributes.backing_store = NotUseful; + + if (pWin->optional) + { + mask |= CWBackingPlanes | CWBackingPixel; + attributes.backing_planes = pWin->optional->backingBitPlanes; + attributes.backing_pixel = pWin->optional->backingPixel; + } + +/* +FIXME: Do we need to set save unders attribute here? +*/ + if (nxagentSaveUnder == True) + { + mask |= CWSaveUnder; + attributes.save_under = pWin->saveUnder; + } + + if (pWin->parent) { + if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent)) { + visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); + mask |= CWColormap; + if (pWin->optional->colormap) { + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP); + attributes.colormap = nxagentColormap(pCmap); + } + else + attributes.colormap = nxagentDefaultVisualColormap(visual); + } + else + visual = CopyFromParent; + } + else { /* root windows have their own colormaps at creation time */ + visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP); + mask |= CWColormap; + attributes.colormap = nxagentColormap(pCmap); + } + } + + if (mask & CWEventMask) + { + nxagentGetEventMask(pWin, (Mask*)&attributes.event_mask); + } + #ifdef WARNING + else + { + attributes.event_mask = NoEventMask; + } + #endif + + #ifdef TEST + fprintf(stderr, "nxagentReconnectWindow: Going to create new window.\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentReconnectWindow: Recreating %swindow at %p current event mask = %lX mask & CWEventMask = %ld " + "event_mask = %lX\n", + nxagentWindowTopLevel(pWin) ? "toplevel " : "", (void*)pWin, pWin -> eventMask, + mask & CWEventMask, attributes.event_mask); + #endif + + /* + * FIXME: This quick hack is intended to solve a + * problem of NXWin X server for windows. + * The NXWin minimize the windows moving them + * out of the screen area, this behaviour + * can cause problem when a rootless session + * is disconnected and an apps is minimized. + * It will be solved with new Xorg version of + * the NXWin server. + */ + + if (nxagentOption(Rootless)) + { + if (pWin -> drawable.x == -32000 && pWin -> drawable.y == -32000) + { + pWin -> drawable.x = (pWin -> drawable.pScreen -> width - pWin -> drawable.width) / 2; + pWin -> drawable.y = (pWin -> drawable.pScreen -> height - pWin -> drawable.height) /2; + } + + if (pWin -> origin.x == -32000 && pWin -> origin.y == -32000) + { + pWin -> origin.x = (pWin -> drawable.pScreen -> width - pWin -> drawable.width) / 2; + pWin -> origin.y = (pWin -> drawable.pScreen -> height - pWin -> drawable.height) / 2; + } + } + + nxagentWindow(pWin) = XCreateWindow(nxagentDisplay, + nxagentWindowParent(pWin), + pWin->origin.x - + wBorderWidth(pWin), + pWin->origin.y - + wBorderWidth(pWin), + pWin->drawable.width, + pWin->drawable.height, + pWin->borderWidth, + pWin->drawable.depth, + pWin->drawable.class, + visual, + mask, + &attributes); + + #ifdef TEST + fprintf(stderr, "nxagentReconnectWindow: Created new window with id [%ld].\n", + nxagentWindowPriv(pWin)->window); + #endif + + /* + * We have to set the WM_DELETE_WINDOW protocols + * on every top level window, because we don't know + * if a client handles this. + */ + + if (nxagentOption(Rootless) && (pWin != WindowTable[0])) + { + if (nxagentWindowTopLevel(pWin)) + { + Atom prop = nxagentMakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), True); + + XlibAtom atom = nxagentMakeAtom("WM_DELETE_WINDOW", strlen("WM_DELETE_WINDOW"), True); + + XSetWMProtocols(nxagentDisplay, nxagentWindow(pWin), &atom, 1); + + nxagentAddPropertyToList(prop, pWin); + } + + nxagentExportAllProperty(pWin); + + if (nxagentWindowTopLevel(pWin)) + { + int ret; + Atom type; + int format; + unsigned long nItems, bytesLeft; + XSizeHints *props, hints; + unsigned char *data = NULL; + + hints.flags = 0; + + ret = GetWindowProperty(pWin, + XA_WM_NORMAL_HINTS, + 0, sizeof(XSizeHints), + False, XA_WM_SIZE_HINTS, + &type, &format, &nItems, &bytesLeft, &data); + + props = (XSizeHints*) data; + + if (ret == Success && + ((format >> 3) * nItems) == sizeof(XSizeHints) && + bytesLeft == 0 && + type == XA_WM_SIZE_HINTS) + { + #ifdef TEST + fprintf(stderr, "nxagentReconnectWindow: setting WMSizeHints on window %p [%lx - %lx].\n", + (void*)pWin, pWin -> drawable.id, nxagentWindow(pWin)); + #endif + + hints = *props; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentReconnectWindow: Failed to get property WM_NORMAL_HINTS on window %p\n", + (void*)pWin); + #endif + } + + hints.flags |= (USPosition | PWinGravity); + hints.x = pWin -> drawable.x; + hints.y = pWin -> drawable.y; + hints.win_gravity = StaticGravity; + + XSetWMNormalHints(nxagentDisplay, + nxagentWindow(pWin), + &hints); + } + } + + if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized) + { + nxagentAllocateCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW); + } +} + +static void nxagentReconfigureWindowCursor(pointer param0, XID param1, pointer data_buffer) +{ + WindowPtr pWin = (WindowPtr)param0; + Bool *pBool = (Bool*)data_buffer; + CursorPtr pCursor; + ScreenPtr pScreen = pWin -> drawable.pScreen; + + if (!pWin || !*pBool || !(pCursor = wCursor(pWin)) || + !(nxagentCursorPriv(pCursor, pScreen))) + { + return; + } + + #ifdef DEBUG + fprintf(stderr, "nxagentReconfigureWindowCursor: %p - ID %lx geometry (%d,%d,%d,%d) " + "cursor %p - ID %lx\n", + pWin, nxagentWindow(pWin), + pWin -> drawable.x, + pWin -> drawable.y, + pWin -> drawable.width, + pWin -> drawable.height, + pCursor, nxagentCursor(pCursor, pScreen)); + #endif + + if (nxagentCursor(pCursor, pScreen) == None) + { + #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG + fprintf(stderr, "nxagentReconfigureWindowCursor: reconnecting valid cursor %lx\n", + (void*)pCursor); + #endif + + nxagentReconnectCursor(pCursor, 0, pBool); + + if (!*pBool) + { + #ifdef WARNING + fprintf(stderr, "nxagentReconfigureWindowCursor: WARNING " + "failed reconnection of cursor at [%p] for window at [%p]: ignoring it.\n", + (void*)pCursor, (void*)pWin); + #endif + + *pBool = True; + } + } + + if (nxagentOption(Rootless)) + { + XDefineCursor(nxagentDisplay,nxagentWindow(pWin),nxagentCursor(pCursor,pScreen)); + } +} + +static void nxagentReconfigureWindow(pointer param0, XID param1, pointer data_buffer) +{ + WindowPtr pWin = (WindowPtr)param0; + unsigned long mask = 0; + + #ifdef DEBUG + fprintf(stderr, "nxagentReconfigureWindow: pWin %p - ID %lx\n", pWin, nxagentWindow(pWin)); + #endif + + if (pWin -> drawable.class == InputOnly) + mask = CWWinGravity | CWEventMask | CWDontPropagate | CWOverrideRedirect | CWCursor; + else + mask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBorderPixel | + CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPlanes | + CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | + CWDontPropagate | CWColormap | CWCursor; + + nxagentChangeWindowAttributes(pWin, mask); + +#ifdef SHAPE + if (nxagentWindowPriv(pWin) -> boundingShape) + { + REGION_DESTROY(pWin -> drawable.pScreen, + nxagentWindowPriv(pWin) -> boundingShape); + nxagentWindowPriv(pWin) -> boundingShape = NULL; + } + + if (nxagentWindowPriv(pWin) -> clipShape) + { + REGION_DESTROY(pWin -> drawable.pScreen, + nxagentWindowPriv(pWin) -> clipShape); + nxagentWindowPriv(pWin) -> clipShape = NULL; + } + nxagentShapeWindow(pWin); +#endif + + if (pWin != WindowTable[0]) + { + if (pWin->realized) + { + nxagentRealizeWindow (pWin); + } + else if (pWin->mapped) + { + XMapWindow(nxagentDisplay, nxagentWindow(pWin)); + } + else if (nxagentOption(Rootless) && pWin -> overrideRedirect == 0 && + nxagentWindowTopLevel(pWin) && nxagentIsIconic(pWin)) + { + MapWindow(pWin, serverClient); + XIconifyWindow(nxagentDisplay, nxagentWindow(pWin), pWin -> drawable.pScreen -> myNum); + } + } + else if (nxagentOption(Rootless) == 0) + { + /* + * Map the root window. + */ + + XMoveWindow(nxagentDisplay, nxagentWindow(pWin), + nxagentOption(RootX), nxagentOption(RootY)); + + XMapWindow(nxagentDisplay, nxagentWindow(pWin)); + } +} + +Bool nxagentCheckIllegalRootMonitoring(WindowPtr pWin, Mask mask) +{ + Mask invalidMask = SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask; + + if (nxagentOption(Rootless) && + pWin == WindowTable[0] && + (mask & invalidMask)) + { + return True; + } + + return False; +} + +#ifdef TEST + +Bool nxagentCheckWindowIntegrity(WindowPtr pWin) +{ + Bool integrity = True; + XImage *image; + char *data; + int format; + unsigned long plane_mask = AllPlanes; + unsigned int width, height, length, depth; + + width = pWin -> drawable.width; + height = pWin -> drawable.height; + depth = pWin -> drawable.depth; + format = (depth == 1) ? XYPixmap : ZPixmap; + + if (width && height) + { + length = nxagentImageLength(width, height, format, 0, depth); + data = malloc(length); + + if (data == NULL) + { + FatalError("nxagentCheckWindowIntegrity: Failed to allocate a buffer of size %d.\n", length); + } + + memset(data, 0, length); + + image = XGetImage(nxagentDisplay, nxagentWindow(pWin), 0, 0, + width, height, plane_mask, format); + if (image == NULL) + { + fprintf(stderr, "XGetImage: Failed.\n"); + return False; + } + + fbGetImage((DrawablePtr)pWin, 0, 0, width, height, format, plane_mask, data); + + if (image && memcmp(image->data, data, length) != 0) + { + #ifdef TEST + int i; + char *p, *q; + #endif + + integrity = False; + + #ifdef TEST + for (i = 0, p = image->data, q = data; i < length; i++) + { + if (p[i] != q[i]) + { + fprintf(stderr, "[%d] %d - %d !!!!!!!!!!!!!!!!!!! **************** !!!!!!!!!!!!!!!!!\n", i, p[i], q[i]); + } + else + { + fprintf(stderr, "[%d] %d - %d\n", i, p[i], q[i]); + } + } + #endif + + #ifdef WARNING + fprintf(stderr, "nxagentCheckWindowIntegrity: Window %p width %d, height %d, has been realized " + "but the data buffer still differs.\n", (void*) pWin, width, height); + fprintf(stderr, "nxagentCheckWindowIntegrity: bytes_per_line = %d byte pad %d format %d.\n", + image -> bytes_per_line, nxagentImagePad(width, height, 0, depth), image->format); + + fprintf(stderr, "nxagentCheckWindowIntegrity: image is corrupted!!\n"); + #endif + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckWindowIntegrity: Window %p has been realized " + "now remote and frambuffer data are synchronized.\n", (void*) pWin); + #endif + } + + if (image) + { + XDestroyImage(image); + } + + if (data) + { + free(data); + } + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentCheckWindowIntegrity: ignored window %p with geometry (%d,%d).\n", + (void*) pWin, width, height); + #endif + } + + return integrity; +} + +#endif + +Bool nxagentIsIconic(WindowPtr pWin) +{ + int iReturn; + unsigned long ulReturnItems; + unsigned long ulReturnBytesLeft; + Atom atomReturnType; + int iReturnFormat; + unsigned char *pszReturnData = NULL; + + if (!wUserProps (pWin)) + { + return 0; + } + + iReturn = GetWindowProperty(pWin, MakeAtom("WM_STATE", 8, False), 0, sizeof(CARD32), False, + AnyPropertyType, &atomReturnType, &iReturnFormat, + &ulReturnItems, &ulReturnBytesLeft, &pszReturnData); + + if (iReturn == Success) + { + return (((CARD32 *)pszReturnData)[0] == IconicState); + } + else + { + return 0; + } +} + +void nxagentSetTopLevelEventMask(pWin) + WindowPtr pWin; +{ + unsigned long mask = CWEventMask; + XSetWindowAttributes attributes; + + if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin)) + { + nxagentGetEventMask(pWin, (Mask*)&attributes.event_mask); + + XChangeWindowAttributes(nxagentDisplay, nxagentWindow(pWin), mask, &attributes); + } +} + +/* + * This function must return 1 if we want the + * exposures to be sent as the window's extents. + * This is actually a harmless, but useful hack, + * as it speeds up the window redraws considera- + * bly, when using a very popular WM theme. + */ + +int nxagentExtentsPredicate(int total) +{ + #ifdef TEST + + if (total == 6 || total == 11 || total == 10) + { + fprintf(stderr, "nxagentExtentsPredicate: WARNING! Returning [%d] with [%d] rectangles.\n", + (total == 6 || total == 11 || total == 10), total); + } + + #endif + + return (total == 6 || total == 11 || total == 10); +} + +void nxagentFlushConfigureWindow(void) +{ + ConfiguredWindowStruct *index; + XWindowChanges changes; + int i; + int j; + + index = nxagentConfiguredWindowList; + + while (index) + { + if (index -> next == NULL) + { + break; + } + + index = index -> next; + } + + while (index) + { + ConfiguredWindowStruct *tmp; + + WindowPtr pWin = index -> pWin; + unsigned int valuemask = index -> valuemask; + + if (pWin && valuemask) + { + nxagentConfigureWindow(pWin, valuemask); + } + + tmp = index; + + if (index == nxagentConfiguredWindowList) + { + free(tmp); + break; + } + + index = index -> prev; + free(tmp); + } + + nxagentConfiguredWindowList = NULL; + + for (j = 0; j < nxagentExposeQueue.length; j++) + { + i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE; + + if (nxagentExposeQueue.exposures[i].synchronize == 1) + { + changes.x = nxagentExposeQueue.exposures[i].serial; + changes.y = -2; + + #ifdef DEBUG + fprintf(stderr, "nxagentFlushConfigureWindow: Sending synch ConfigureWindow for " + "index [%d] serial [%d].\n", i, nxagentExposeQueue.exposures[i].serial); + #endif + + XConfigureWindow(nxagentDisplay, nxagentConfiguredSynchroWindow, + CWX | CWY, &changes); + + nxagentExposeQueue.exposures[i].synchronize = 0; + } + } + + nxagentSendDeferredBackgroundExposures(); + + return; +} + +void nxagentPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ +/* +FIXME: Do we need this here? + + nxagentFlushConfigureWindow(); +*/ + + return; +} + +void nxagentAddConfiguredWindow(WindowPtr pWin, unsigned int valuemask) +{ + unsigned int mask; + + mask = valuemask & (CWParent | CWX | CWY | CWWidth | CWHeight | + CWBorderWidth | CWStackingOrder | CW_Map | CW_Update | CW_Shape); + + valuemask &= ~(CWParent | CWX | CWY | CWWidth | CWHeight | CWBorderWidth | CWStackingOrder); + + if (mask & CWX && + nxagentWindowPriv(pWin)->x != + pWin->origin.x - wBorderWidth(pWin)) + { + valuemask |= CWX; + } + + if (mask & CWY && + nxagentWindowPriv(pWin)->y != + pWin->origin.y - wBorderWidth(pWin)) + { + valuemask |= CWY; + } + + if (mask & CWWidth && + nxagentWindowPriv(pWin)->width != + pWin->drawable.width) + { + valuemask |= CWWidth; + } + + if (mask & CWHeight && + nxagentWindowPriv(pWin)->height != + pWin->drawable.height) + { + valuemask |= CWHeight; + } + + if (mask & CWBorderWidth && + nxagentWindowPriv(pWin)->borderWidth != + pWin->borderWidth) + { + valuemask |= CWBorderWidth; + } + + if (mask & CWStackingOrder && + nxagentWindowPriv(pWin)->siblingAbove != + nxagentWindowSiblingAbove(pWin)) + { + valuemask |= CWStackingOrder; + } + + if (nxagentConfiguredWindowList == NULL) + { + nxagentConfiguredWindowList = malloc(sizeof(ConfiguredWindowStruct)); + nxagentConfiguredWindowList -> next = NULL; + nxagentConfiguredWindowList -> prev = NULL; + + nxagentConfiguredWindowList -> pWin = pWin; + } + else + { + ConfiguredWindowStruct *tmp; + + tmp = malloc(sizeof(ConfiguredWindowStruct)); + + tmp -> next = nxagentConfiguredWindowList; + nxagentConfiguredWindowList -> prev = tmp; + tmp -> prev = NULL; + nxagentConfiguredWindowList = tmp; + nxagentConfiguredWindowList -> pWin = pWin; + } + + nxagentConfiguredWindowList -> valuemask = valuemask; + + return; +} + +void nxagentDeleteConfiguredWindow(WindowPtr pWin) +{ + ConfiguredWindowStruct *index, *previous, *tmp; + + index = nxagentConfiguredWindowList; + + while (index) + { + WindowPtr pDel = index -> pWin; + + if (pDel == pWin) + { + if (index -> prev == NULL && index -> next == NULL) + { + free(nxagentConfiguredWindowList); + nxagentConfiguredWindowList = NULL; + + return; + } + else if (index -> prev == NULL) + { + tmp = nxagentConfiguredWindowList; + index = nxagentConfiguredWindowList = tmp -> next; + free(tmp); + nxagentConfiguredWindowList -> prev = NULL; + + continue; + } + else if (index -> next == NULL) + { + tmp = index; + index = index -> prev; + free(tmp); + index -> next = NULL; + + return; + } + + previous = index -> prev; + tmp = index; + index = index -> next; + previous -> next = index; + index -> prev = previous; + free(tmp); + + continue; + } + + index = index -> next; + } + + return; +} + +void nxagentEmptyBackingStoreRegion(pointer param0, XID param1, pointer data_buffer) +{ + WindowPtr pWin = (WindowPtr) param0; + + miBSWindowPtr pBackingStore = (miBSWindowPtr)pWin->backStorage; + + if (pBackingStore != NULL) + { + REGION_EMPTY(pWin -> pScreen, &pBackingStore->SavedRegion); + + #ifdef TEST + fprintf(stderr, "nxagentEmptyBackingStoreRegion: Emptying saved region for window at [%p].\n", (void*) pWin); + #endif + + if (pBackingStore -> pBackingPixmap != NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentEmptyBackingStoreRegion: Emptying corrupted region for drawable at [%p].\n", + (void*) pBackingStore -> pBackingPixmap); + #endif + + nxagentUnmarkCorruptedRegion((DrawablePtr) pBackingStore -> pBackingPixmap, NullRegion); + } + } +} + +void nxagentEmptyAllBackingStoreRegions(void) +{ + if (nxagentLoopOverWindows(nxagentEmptyBackingStoreRegion) == 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentEmptyAllSavedRegions: Failed to empty backing store saved regions.\n"); + #endif + } +} + +void nxagentInitBSPixmapList(void) +{ + memset(nxagentBSPixmapList, 0, BSPIXMAPLIMIT * sizeof( StoringPixmapPtr)); +} + +int nxagentAddItemBSPixmapList(unsigned long id, PixmapPtr pPixmap, WindowPtr pWin, int bsx, int bsy) +{ + int i; + + for (i = 0; i < BSPIXMAPLIMIT; i++) + { + if (nxagentBSPixmapList[i] == NULL) + { + nxagentBSPixmapList[i] = malloc(sizeof(StoringPixmapRec)); + + if (nxagentBSPixmapList[i] == NULL) + { + FatalError("nxagentAddItemBSPixmapList: Failed to allocate memory for nxagentBSPixmapList.\n"); + } + + nxagentBSPixmapList[i] -> storingPixmapId = id; + nxagentBSPixmapList[i] -> pStoringPixmap = pPixmap; + nxagentBSPixmapList[i] -> pSavedWindow = pWin; + nxagentBSPixmapList[i] -> backingStoreX = bsx; + nxagentBSPixmapList[i] -> backingStoreY = bsy; + + #ifdef TEST + fprintf(stderr, "nxagentAddItemBSPixmapList: Added Pixmap with id [%lu] to nxagentBSPixmapList.\n", id); + #endif + + return 1; + } + + if (nxagentBSPixmapList[i] -> storingPixmapId == id) + { + nxagentBSPixmapList[i] -> pStoringPixmap = pPixmap; + nxagentBSPixmapList[i] -> pSavedWindow = pWin; + nxagentBSPixmapList[i] -> backingStoreX = bsx; + nxagentBSPixmapList[i] -> backingStoreY = bsy; + + #ifdef TEST + fprintf(stderr, "nxagentAddItemBSPixmapList: Updated existing item for id [%lu].\n", id); + #endif + + return 1; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentAddItemBSPixmapList: WARNING! List item full.\n"); + #endif + + return 0; +} + +int nxagentRemoveItemBSPixmapList(unsigned long pixmapId) +{ + int i; + int j; + + if (pixmapId == 0 || nxagentBSPixmapList[0] == NULL) + { + return 0; + } + + for (i = 0; i < BSPIXMAPLIMIT; i++) + { + if ((nxagentBSPixmapList[i] != NULL) && + (nxagentBSPixmapList[i] -> storingPixmapId == pixmapId)) + { + free(nxagentBSPixmapList[i]); + nxagentBSPixmapList[i] = NULL; + + if (i < BSPIXMAPLIMIT - 1) + { + for (j = i; j < BSPIXMAPLIMIT -1; j++) + { + nxagentBSPixmapList[j] = nxagentBSPixmapList[j + 1]; + } + + if (nxagentBSPixmapList[j] == nxagentBSPixmapList[j - 1]) + { + nxagentBSPixmapList[j] = NULL; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentRemoveItemBSPixmapList: Removed Pixmap with id [%lu] from list.\n", + pixmapId); + #endif + + return 1; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentRemoveItemBSPixmapList: WARNING! Can't remove item [%lu]: item not found.\n", + pixmapId); + #endif + + return 0; +} + +int nxagentEmptyBSPixmapList() +{ + int i; + + for (i = 0; i < BSPIXMAPLIMIT; i++) + { + if (nxagentBSPixmapList[i] != NULL) + { + free(nxagentBSPixmapList[i]); + nxagentBSPixmapList[i] = NULL; + } + } + + return 1; +} + +StoringPixmapPtr nxagentFindItemBSPixmapList(unsigned long pixmapId) +{ + int i; + + for (i = 0; i < BSPIXMAPLIMIT; i++) + { + if ((nxagentBSPixmapList[i] != NULL) && + (nxagentBSPixmapList[i] -> storingPixmapId == pixmapId)) + { + #ifdef TEST + fprintf(stderr, "nxagentFindItemBSPixmapList: pixmapId [%lu].\n", pixmapId); + fprintf(stderr, "nxagentFindItemBSPixmapList: nxagentBSPixmapList[%d] -> storingPixmapId [%lu].\n", + i, nxagentBSPixmapList[i] -> storingPixmapId); + #endif + + return nxagentBSPixmapList[i]; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentFindItemBSPixmapList: WARNING! Item not found.\n"); + #endif + + #ifdef TEST + fprintf(stderr, "nxagentFindItemBSPixmapList: Pixmap with id [%lu] not found.\n", + pixmapId); + fprintf(stderr, "nxagentBSPixmapList[%d] = [%p].\n", + i, (void *) nxagentBSPixmapList[i]); + #endif + + return NULL; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/Windows.h b/nx-X11/programs/Xserver/hw/nxagent/Windows.h new file mode 100644 index 000000000..239d558b4 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Windows.h @@ -0,0 +1,300 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#ifndef __Window_H__ +#define __Window_H__ + +#include "Options.h" +#include "Rootless.h" +#include "Pixmaps.h" + +#include "validate.h" + +typedef struct +{ + Window window; + int x; + int y; + unsigned int width; + unsigned int height; + unsigned int borderWidth; + Window siblingAbove; + int backingStore; +#ifdef SHAPE + RegionPtr boundingShape; + RegionPtr clipShape; +#endif /* SHAPE */ + + void *pPicture; + + /* + * Set if the window is mapped + * on the remote server. + */ + + int isMapped; + + /* + * Set if the window on the remote + * server is redirected by using + * the composite extension. + */ + + int isRedirected; + + int visibilityState; + + RegionPtr corruptedRegion; + + int hasTransparentChildren; + + int containGlyphs; + + int deferredBackgroundExpose; + + XID corruptedId; + + PixmapPtr synchronizationBitmap; + + Time corruptedTimestamp; + + SplitResourcePtr splitResource; + +} nxagentPrivWindowRec; + +typedef nxagentPrivWindowRec *nxagentPrivWindowPtr; + +typedef struct +{ + unsigned long storingPixmapId; + + PixmapPtr pStoringPixmap; + + WindowPtr pSavedWindow; + + int backingStoreX; + + int backingStoreY; + +} StoringPixmapRec; + +typedef StoringPixmapRec *StoringPixmapPtr; + +int nxagentAddItemBSPixmapList(unsigned long, PixmapPtr, WindowPtr, int, int); +int nxagentRemoveItemBSPixmapList(unsigned long); +void nxagentInitBSPixmapList(void); +int nxagentEmptyBSPixmapList(void); +StoringPixmapPtr nxagentFindItemBSPixmapList (unsigned long); + +extern int nxagentWindowPrivateIndex; + +#define nxagentWindowPriv(pWin) \ + ((nxagentPrivWindowPtr)((pWin)->devPrivates[nxagentWindowPrivateIndex].ptr)) + +#define nxagentWindow(pWin) (nxagentWindowPriv(pWin)->window) + +/* + * Window is either a child of our root + * or a child of the root of the real X + * server. + */ + +#define nxagentWindowParent(pWin) \ + (nxagentOption(Rootless) ? \ + nxagentRootlessWindowParent(pWin) : \ + ((pWin)->parent ? \ + nxagentWindow((pWin)->parent) : \ + nxagentDefaultWindows[pWin->drawable.pScreen->myNum])) + +/* + * True if this is a top level window. + */ + +#define nxagentWindowTopLevel(pWin) \ + (pWin && (pWin -> parent == NULL || \ + pWin->parent == nxagentRootlessWindow)) + +#define nxagentWindowSiblingAbove(pWin) \ + ((pWin)->prevSib ? nxagentWindow((pWin)->prevSib) : None) + +#define nxagentWindowSiblingBelow(pWin) \ + ((pWin)->nextSib ? nxagentWindow((pWin)->nextSib) : None) + +#define nxagentWindowCorruptedRegion(pWin) \ + (nxagentWindowPriv(pWin) -> corruptedRegion) + +#define nxagentWindowContainGlyphs(pWin) \ + (nxagentWindowPriv(pWin) -> containGlyphs) + +#define nxagentWindowTimestamp(pWin) \ + (nxagentWindowPriv(pWin) -> corruptedTimestamp) + +#define nxagentWindowIsVisible(pWin) \ + ((pWin) -> viewable == 1 && \ + (pWin) -> drawable.class != InputOnly && \ + (pWin) -> visibility != VisibilityFullyObscured) + +#define nxagentDefaultWindowIsVisible() \ + (nxagentVisibility != VisibilityFullyObscured) + +#define CWParent CWSibling +#define CWStackingOrder CWStackMode + +#define CW_Map (1 << 15) +#define CW_Update (1 << 16) +#define CW_Shape (1 << 17) +#define CW_RootlessRestack (1 << 18) + +/* + * This force the agent to send exposures + * for all windows. + */ + +#define nxagentRefreshScreen() \ +do\ +{\ + nxagentRefreshWindows(WindowTable[0]);\ +} while (0) + +WindowPtr nxagentWindowPtr(Window window); + +extern Atom serverCutProperty; + +/* + * If the rectangles in an exposed region exceed + * the number of 4, we let the function decide if + * it is better to send the window extents rather + * than the rectangles in the region. + */ + +int nxagentExtentsPredicate(int total); + +/* + * Agent's nested window procedures. Look also + * at Rootless.h for the rootless counterparts. + */ + +Bool nxagentCreateWindow(WindowPtr pWin); + +Bool nxagentDestroyWindow(WindowPtr pWin); + +Bool nxagentPositionWindow(WindowPtr pWin, int x, int y); + +Bool nxagentChangeWindowAttributes(WindowPtr pWin, unsigned long mask); + +Bool nxagentRealizeWindow(WindowPtr pWin); + +Bool nxagentUnrealizeWindow(WindowPtr pWin); + +Bool nxagentCheckIllegalRootMonitoring(WindowPtr pWin, Mask mask); + +void nxagentWindowExposures(WindowPtr pWin, RegionPtr pRgn, RegionPtr other_exposed); + +void nxagentPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what); + +void nxagentPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what); + +void nxagentCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion); + +void nxagentClipNotify(WindowPtr pWin, int dx, int dy); + +void nxagentRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib); + +void nxagentReparentWindow(WindowPtr pWin, WindowPtr pOldParent); + +void nxagentRefreshWindows(WindowPtr pWin); + +void nxagentSetTopLevelEventMask(WindowPtr pWin); + +void nxagentSwitchFullscreen(ScreenPtr pScreen, Bool switchOn); + +void nxagentMoveViewport(ScreenPtr pScreen, int hShift, int vShift); + +#ifdef VIEWPORT_FRAME + +void nxagentUpdateViewportFrame(int x, int y, int w, int h); + +#else /* #ifdef VIEWPORT_FRAME */ + +#define nxagentUpdateViewportFrame(x, y, w, h) + +#endif /* #ifdef VIEWPORT_FRAME */ + +void nxagentUnmapWindows(void); + +void nxagentMapDefaultWindows(void); + +Bool nxagentSetWindowCursors(void *p0); + +/* + * The ConfigureWindow procedure has not + * a pointer in the screen structure. + */ + +void nxagentConfigureWindow(WindowPtr pWin, unsigned int mask); + +/* + * Used to track nxagent window's visibility. + */ + +extern int nxagentVisibility; +extern unsigned long nxagentVisibilityTimeout; +extern Bool nxagentVisibilityStop; + +/* + * Return the pointer to the window given the + * remote id. It tries to match the id from + * the last matched window before iterating + * through the hierarchy. + */ + +WindowPtr nxagentGetWindowFromID(Window id); + +/* + * Handle the shape bitmap for windows. + */ + +#ifdef SHAPE + +void nxagentShapeWindow(WindowPtr pWin); + +#endif + +extern Window nxagentConfiguredSynchroWindow; +extern Bool nxagentExposeArrayIsInitialized; + +typedef struct _ConfiguredWindow +{ + WindowPtr pWin; + struct _ConfiguredWindow *next; + struct _ConfiguredWindow *prev; + unsigned int valuemask; +} ConfiguredWindowStruct; + +ConfiguredWindowStruct *nxagentConfiguredWindowList; + +void nxagentPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind); + +void nxagentFlushConfigureWindow(void); + +void nxagentAddConfiguredWindow(WindowPtr pWin, unsigned int valuemask); + +void nxagentDeleteConfiguredWindow(WindowPtr pWin); + +void nxagentEmptyAllBackingStoreRegions(void); + +#endif /* __Window_H__ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c new file mode 100644 index 000000000..c49f1587f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c @@ -0,0 +1,2073 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $Id: damage.c,v 1.19 2005/10/06 21:55:41 anholt Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "damage.h" +#include "damagestr.h" +#ifdef COMPOSITE +#include "cw.h" +#endif + +#define wrap(priv, real, mem, func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +#define BOX_SAME(a,b) \ + ((a)->x1 == (b)->x1 && \ + (a)->y1 == (b)->y1 && \ + (a)->x2 == (b)->x2 && \ + (a)->y2 == (b)->y2) + +#define DAMAGE_VALIDATE_ENABLE 0 +#define DAMAGE_DEBUG_ENABLE 0 +#if DAMAGE_DEBUG_ENABLE +#define DAMAGE_DEBUG(x) ErrorF x +#else +#define DAMAGE_DEBUG(x) +#endif + +#define getPixmapDamageRef(pPixmap) \ + ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr)) + +#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) + +static DamagePtr * +getDrawableDamageRef (DrawablePtr pDrawable) +{ + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW) + { + ScreenPtr pScreen = pDrawable->pScreen; + + pPixmap = 0; + if (pScreen->GetWindowPixmap +#ifdef ROOTLESS_WORKAROUND + && ((WindowPtr)pDrawable)->viewable +#endif + ) + pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable); + + if (!pPixmap) + { + damageScrPriv(pScreen); + + return &pScrPriv->pScreenDamage; + } + } + else + pPixmap = (PixmapPtr) pDrawable; + return getPixmapDamageRef (pPixmap); +} + +#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable)) +#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable) + +#define drawableDamage(pDrawable) \ + DamagePtr pDamage = getDrawableDamage(pDrawable) + +#define windowDamage(pWin) drawableDamage(&(pWin)->drawable) + +#define winDamageRef(pWindow) \ + DamagePtr *pPrev = (DamagePtr *) \ + &(pWindow->devPrivates[damageWinPrivateIndex].ptr) + +#if DAMAGE_DEBUG_ENABLE +static void +_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) +#define damageDamageRegion(d,r,c,m) _damageDamageRegion(d,r,c,m,__FUNCTION__) +#else +static void +damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, + int subWindowMode) +#endif +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + drawableDamage(pDrawable); + DamagePtr pNext; + RegionRec clippedRec; + RegionPtr pDamageRegion; + RegionRec pixClip; + Bool was_empty; + RegionRec tmpRegion; + BoxRec tmpBox; + int draw_x, draw_y; +#ifdef COMPOSITE + int screen_x = 0, screen_y = 0; +#endif + + /* short circuit for empty regions */ + if (!REGION_NOTEMPTY(pScreen, pRegion)) + return; + +#ifdef COMPOSITE + /* + * When drawing to a pixmap which is storing window contents, + * the region presented is in pixmap relative coordinates which + * need to be converted to screen relative coordinates + */ + if (pDrawable->type != DRAWABLE_WINDOW) + { + screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; + screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; + } + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y); +#endif + + if (pDrawable->type == DRAWABLE_WINDOW && + ((WindowPtr)(pDrawable))->backingStore == NotUseful) + { + if (subWindowMode == ClipByChildren) + { + REGION_INTERSECT(pScreen, pRegion, pRegion, + &((WindowPtr)(pDrawable))->clipList); + } + else if (subWindowMode == IncludeInferiors) + { + RegionPtr pTempRegion = + NotClippedByChildren((WindowPtr)(pDrawable)); + REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); + REGION_DESTROY(pScreen, pTempRegion); + } + /* If subWindowMode is set to an invalid value, don't perform + * any drawable-based clipping. */ + } + + + REGION_NULL (pScreen, &clippedRec); + for (; pDamage; pDamage = pNext) + { + pNext = pDamage->pNext; + /* + * Check for internal damage and don't send events + */ + if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) + { + DAMAGE_DEBUG (("non internal damage, skipping at %d\n", + pScrPriv->internalLevel)); + continue; + } + /* + * Check for unrealized windows + */ + if (pDamage->pDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr) (pDamage->pDrawable))->realized) + { +#if 0 + DAMAGE_DEBUG (("damage while window unrealized\n")); +#endif + continue; + } + + draw_x = pDamage->pDrawable->x; + draw_y = pDamage->pDrawable->y; +#ifdef COMPOSITE + /* + * Need to move everyone to screen coordinates + * XXX what about off-screen pixmaps with non-zero x/y? + */ + if (pDamage->pDrawable->type != DRAWABLE_WINDOW) + { + draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x; + draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y; + } +#endif + + /* + * Clip against border or pixmap bounds + */ + + pDamageRegion = pRegion; + if (clip || pDamage->pDrawable != pDrawable) + { + pDamageRegion = &clippedRec; + if (pDamage->pDrawable->type == DRAWABLE_WINDOW) { + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, + &((WindowPtr)(pDamage->pDrawable))->borderClip); + } else { + BoxRec box; + box.x1 = draw_x; + box.y1 = draw_y; + box.x2 = draw_x + pDamage->pDrawable->width; + box.y2 = draw_y + pDamage->pDrawable->height; + REGION_INIT(pScreen, &pixClip, &box, 1); + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip); + REGION_UNINIT(pScreen, &pixClip); + } + /* + * Short circuit empty results + */ + if (!REGION_NOTEMPTY(pScreen, pDamageRegion)) + continue; + } + + DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n", + where, + pDamageRegion->extents.x2 - pDamageRegion->extents.x1, + pDamageRegion->extents.y2 - pDamageRegion->extents.y1, + pDamageRegion->extents.x1, pDamageRegion->extents.y1, + pDrawable->id, pDamage->pDrawable->id)); + + /* + * Move region to target coordinate space + */ + if (draw_x || draw_y) + REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + REGION_NULL (pScreen, &tmpRegion); + REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage); + if (REGION_NOTEMPTY (pScreen, &tmpRegion)) + { + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); + } + REGION_UNINIT(pScreen, &tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNonEmpty: + was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNone: + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + break; + } + /* + * translate original region back + */ + if (pDamageRegion == pRegion && (draw_x || draw_y)) + REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y); + } +#ifdef COMPOSITE + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y); +#endif + + REGION_UNINIT (pScreen, &clippedRec); +} + +#if DAMAGE_DEBUG_ENABLE +#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) +static void +_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where) +#else +static void +damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) +#endif +{ + RegionRec region; + + REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1); +#if DAMAGE_DEBUG_ENABLE + _damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode, where); +#else + damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode); +#endif + REGION_UNINIT (pDrawable->pScreen, ®ion); +} + +static void damageValidateGC(GCPtr, unsigned long, DrawablePtr); +static void damageChangeGC(GCPtr, unsigned long); +static void damageCopyGC(GCPtr, unsigned long, GCPtr); +static void damageDestroyGC(GCPtr); +static void damageChangeClip(GCPtr, int, pointer, int); +static void damageDestroyClip(GCPtr); +static void damageCopyClip(GCPtr, GCPtr); + +GCFuncs damageGCFuncs = { + damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, + damageChangeClip, damageDestroyClip, damageCopyClip +}; + +extern GCOps damageGCOps; + +static Bool +damageCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + damageScrPriv(pScreen); + damageGCPriv(pGC); + Bool ret; + + pGC->pCompositeClip = 0; + unwrap (pScrPriv, pScreen, CreateGC); + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; + } + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + + return ret; +} + +#ifdef NOTUSED +static void +damageWrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; +} + +static void +damageUnwrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGC->funcs = pGCPriv->funcs; + if (pGCPriv->ops) + pGC->ops = pGCPriv->ops; +} +#endif + +#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ + damageGCPriv(pGC); \ + GCFuncs *oldFuncs = pGC->funcs; \ + unwrap(pGCPriv, pGC, funcs); \ + unwrap(pGCPriv, pGC, ops); \ + +#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \ + wrap(pGCPriv, pGC, funcs, oldFuncs); \ + wrap(pGCPriv, pGC, ops, &damageGCOps) + +#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \ + damageGCPriv(pGC); \ + unwrap(pGCPriv, pGC, funcs); \ + if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) + +#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \ + wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \ + if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps) + +static void +damageValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDrawable) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageDestroyGC(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageChangeGC (GCPtr pGC, + unsigned long mask) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + DAMAGE_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +damageChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + DAMAGE_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + DAMAGE_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +damageDestroyClip(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ + BoxPtr extents = &pGC->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define TRANSLATE_BOX(box, pDrawable) { \ + box.x1 += pDrawable->x; \ + box.x2 += pDrawable->x; \ + box.y1 += pDrawable->y; \ + box.y2 += pDrawable->y; \ + } + +#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ + TRANSLATE_BOX(box, pDrawable); \ + TRIM_BOX(box, pGC); \ + } + +#define BOX_NOT_EMPTY(box) \ + (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) + +#define checkGCDamage(d,g) (getDrawableDamage(d) && \ + (!g->pCompositeClip ||\ + REGION_NOTEMPTY(d->pScreen, \ + g->pCompositeClip))) + +#ifdef RENDER + +#define TRIM_PICTURE_BOX(box, pDst) { \ + BoxPtr extents = &pDst->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \ + REGION_NOTEMPTY(pScreen, p->pCompositeClip)) + +static void +damageComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + BoxRec box; + + box.x1 = xDst + pDst->pDrawable->x; + box.y1 = yDst + pDst->pDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + TRIM_PICTURE_BOX(box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + wrap (pScrPriv, ps, Composite, damageComposite); +} + +static void +damageGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + int nlistTmp = nlist; + GlyphListPtr listTmp = list; + GlyphPtr *glyphsTmp = glyphs; + int x, y; + int n; + GlyphPtr glyph; + BoxRec box; + int x1, y1, x2, y2; + + box.x1 = 32767; + box.y1 = 32767; + box.x2 = -32767; + box.y2 = -32767; + x = pDst->pDrawable->x; + y = pDst->pDrawable->y; + while (nlistTmp--) + { + x += listTmp->xOff; + y += listTmp->yOff; + n = listTmp->len; + while (n--) + { + glyph = *glyphsTmp++; + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + if (x1 < box.x1) + box.x1 = x1; + if (y1 < box.y1) + box.y1 = y1; + if (x2 > box.x2) + box.x2 = x2; + if (y2 > box.y2) + box.y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + listTmp++; + } + TRIM_PICTURE_BOX (box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + wrap (pScrPriv, ps, Glyphs, damageGlyphs); +} +#endif + +/**********************************************************/ + + +static void +damageFillSpans(DrawablePtr pDrawable, + GC *pGC, + int npt, + DDXPointPtr ppt, + int *pwidth, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageSetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr ppt, + int *pwidth, + int npt, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + int nptTmp = npt; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = x + pDrawable->x; + box.x2 = box.x1 + w; + box.y1 = y + pDrawable->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, + leftPad, format, pImage); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static RegionPtr +damageCopyArea(DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && + pSrc->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + } + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static RegionPtr +damageCopyPlane(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long bitPlane) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && + pSrc->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + } + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static void +damagePolyPoint(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + xPoint *ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nptTmp = npt; + xPoint *pptTmp = ppt; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + /* this could be slow if the points were spread out */ + + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolylines(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(nptTmp > 1) + { + if(pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if(pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if(mode == CoordModePrevious) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolySegment(DrawablePtr pDrawable, + GCPtr pGC, + int nSeg, + xSegment *pSeg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nSeg && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int extra = pGC->lineWidth; + int nsegTmp = nSeg; + xSegment *pSegTmp = pSeg; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSegTmp->x2 > pSegTmp->x1) { + box.x1 = pSegTmp->x1; + box.x2 = pSegTmp->x2; + } else { + box.x2 = pSegTmp->x1; + box.x1 = pSegTmp->x2; + } + + if(pSegTmp->y2 > pSegTmp->y1) { + box.y1 = pSegTmp->y1; + box.y2 = pSegTmp->y2; + } else { + box.y2 = pSegTmp->y1; + box.y1 = pSegTmp->y2; + } + + while(--nsegTmp) + { + pSegTmp++; + if(pSegTmp->x2 > pSegTmp->x1) + { + if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; + if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; + } + else + { + if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; + if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; + } + if(pSegTmp->y2 > pSegTmp->y1) + { + if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; + if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; + } + else + { + if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; + if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyRectangle(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int offset1, offset2, offset3; + int nRectsTmp = nRects; + xRectangle *pRectsTmp = pRects; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while(nRectsTmp--) + { + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + pRectsTmp++; + } + } + (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + int extra = pGC->lineWidth >> 1; + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageFillPolygon(DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt > 2 && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int nptTmp = npt; + BoxRec box; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(mode != CoordModeOrigin) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + xRectangle *pRectsTmp = pRects; + int nRectsTmp = nRects; + + box.x1 = pRectsTmp->x; + box.x2 = box.x1 + pRectsTmp->width; + box.y1 = pRectsTmp->y; + box.y2 = box.y1 + pRectsTmp->height; + + while(--nRectsTmp) + { + pRectsTmp++; + if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x; + if(box.x2 < (pRectsTmp->x + pRectsTmp->width)) + box.x2 = pRectsTmp->x + pRectsTmp->width; + if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y; + if(box.y2 < (pRectsTmp->y + pRectsTmp->height)) + box.y2 = pRectsTmp->y + pRectsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +/* + * general Poly/Image text function. Extract glyph information, + * compute bounding box and remove cursor if it is overlapped. + */ + +static void +damageDamageChars (DrawablePtr pDrawable, + FontPtr font, + int x, + int y, + unsigned int n, + CharInfoPtr *charinfo, + Bool imageblt, + int subWindowMode) +{ + ExtentInfoRec extents; + BoxRec box; + + QueryGlyphExtents(font, charinfo, n, &extents); + if (imageblt) + { + if (extents.overallWidth > extents.overallRight) + extents.overallRight = extents.overallWidth; + if (extents.overallWidth < extents.overallLeft) + extents.overallLeft = extents.overallWidth; + if (extents.overallLeft > 0) + extents.overallLeft = 0; + if (extents.fontAscent > extents.overallAscent) + extents.overallAscent = extents.fontAscent; + if (extents.fontDescent > extents.overallDescent) + extents.overallDescent = extents.fontDescent; + } + box.x1 = x + extents.overallLeft; + box.y1 = y - extents.overallAscent; + box.x2 = x + extents.overallRight; + box.y2 = y + extents.overallDescent; + damageDamageBox (pDrawable, &box, subWindowMode); +} + +/* + * values for textType: + */ +#define TT_POLY8 0 +#define TT_IMAGE8 1 +#define TT_POLY16 2 +#define TT_IMAGE16 3 + +static int +damageText (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned long count, + char *chars, + FontEncoding fontEncoding, + Bool textType) +{ + CharInfoPtr *charinfo; + CharInfoPtr *info; + unsigned long i; + unsigned int n; + int w; + Bool imageblt; + + imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); + + charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); + if (!charinfo) + return x; + + GetGlyphs(pGC->font, count, (unsigned char *)chars, + fontEncoding, &i, charinfo); + n = (unsigned int)i; + w = 0; + if (!imageblt) + for (info = charinfo; i--; info++) + w += (*info)->metrics.characterWidth; + + if (n != 0) { + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, + charinfo, imageblt, pGC->subWindowMode); + +#ifndef NXAGENT_SERVER + + if (imageblt) + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + else + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); +#endif + + } + DEALLOCATE_LOCAL(charinfo); + return x + w; +} + +#ifndef NXAGENT_SERVER + +static int +damagePolyText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + else + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static int +damagePolyText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_POLY16); + else + x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static void +damageImageText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_IMAGE8); + else + (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageImageText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_IMAGE16); + else + (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +#else /* #ifndef NXAGENT_SERVER */ + +static int +damagePolyText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static int +damagePolyText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_POLY16); + + x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static void +damageImageText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_IMAGE8); + + (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageImageText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_IMAGE16); + + (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +#endif /* #ifndef NXAGENT_SERVER */ + +static void +damageImageGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, TRUE, pGC->subWindowMode); + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, FALSE, pGC->subWindowMode); + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePushPixels(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if(checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = xOrg; + box.y1 = yOrg; + + if(!pGC->miTranslate) { + box.x1 += pDrawable->x; + box.y1 += pDrawable->y; + } + + box.x2 = box.x1 + dx; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNext; + return; + } + pPrev = &(*pPrev)->pNext; + } +#if DAMAGE_VALIDATE_ENABLE + ErrorF ("Damage not on list\n"); + abort (); +#endif +} + +static void +damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNext) + if (pOld == pDamage) { + ErrorF ("Damage already on list\n"); + abort (); + } +#endif + pDamage->pNext = *pPrev; + *pPrev = pDamage; +} + +static Bool +damageDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + damageScrPriv(pScreen); + + if (pPixmap->refcnt == 1) + { + DamagePtr *pPrev = getPixmapDamageRef (pPixmap); + DamagePtr pDamage; + + while ((pDamage = *pPrev)) + { + damageRemoveDamage (pPrev, pDamage); + if (!pDamage->isWindow) + DamageDestroy (pDamage); + } + } + unwrap (pScrPriv, pScreen, DestroyPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + return TRUE; +} + +static void +damagePaintWindow(WindowPtr pWindow, + RegionPtr prgn, + int what) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + /* + * Painting background none doesn't actually *do* anything, so + * no damage is recorded + */ + if ((what != PW_BACKGROUND || pWindow->backgroundState != None) && + getWindowDamage (pWindow)) + damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); + if(what == PW_BACKGROUND) { + unwrap (pScrPriv, pScreen, PaintWindowBackground); + (*pScreen->PaintWindowBackground) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + } else { + unwrap (pScrPriv, pScreen, PaintWindowBorder); + (*pScreen->PaintWindowBorder) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + } +} + + +static void +damageCopyWindow(WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if (getWindowDamage (pWindow)) + { + int dx = pWindow->drawable.x - ptOldOrg.x; + int dy = pWindow->drawable.y - ptOldOrg.y; + + /* + * The region comes in source relative, but the damage occurs + * at the destination location. Translate back and forth. + */ + REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); + damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1); + REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); + } + unwrap (pScrPriv, pScreen, CopyWindow); + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); +} + +GCOps damageGCOps = { + damageFillSpans, damageSetSpans, + damagePutImage, damageCopyArea, + damageCopyPlane, damagePolyPoint, + damagePolylines, damagePolySegment, + damagePolyRectangle, damagePolyArc, + damageFillPolygon, damagePolyFillRect, + damagePolyFillArc, damagePolyText8, + damagePolyText16, damageImageText8, + damageImageText16, damageImageGlyphBlt, + damagePolyGlyphBlt, damagePushPixels, +#ifdef NEED_LINEHELPER + NULL, +#endif + {NULL} /* devPrivate */ +}; + +static void +damageRestoreAreas (PixmapPtr pPixmap, + RegionPtr prgn, + int xorg, + int yorg, + WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, + xorg, yorg, pWindow); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +} + +static void +damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if ((pDamage = damageGetWinPriv(pWindow))) + { + PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow); + DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap); + + while (pDamage) + { + damageRemoveDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } + unwrap (pScrPriv, pScreen, SetWindowPixmap); + (*pScreen->SetWindowPixmap) (pWindow, pPixmap); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + if ((pDamage = damageGetWinPriv(pWindow))) + { + DamagePtr *pPrev = getPixmapDamageRef(pPixmap); + + while (pDamage) + { + damageInsertDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } +} + +static Bool +damageDestroyWindow (WindowPtr pWindow) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + Bool ret; + damageScrPriv(pScreen); + + while ((pDamage = damageGetWinPriv(pWindow))) + { + DamageUnregister (&pWindow->drawable, pDamage); + DamageDestroy (pDamage); + } + unwrap (pScrPriv, pScreen, DestroyWindow); + ret = (*pScreen->DestroyWindow) (pWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + return ret; +} + +static Bool +damageCloseScreen (int i, ScreenPtr pScreen) +{ + damageScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, DestroyPixmap); + unwrap (pScrPriv, pScreen, CreateGC); + unwrap (pScrPriv, pScreen, PaintWindowBackground); + unwrap (pScrPriv, pScreen, PaintWindowBorder); + unwrap (pScrPriv, pScreen, CopyWindow); + unwrap (pScrPriv, pScreen, CloseScreen); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + xfree (pScrPriv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +int damageScrPrivateIndex; +int damagePixPrivateIndex; +int damageGCPrivateIndex; +int damageWinPrivateIndex; +int damageGeneration; + +Bool +DamageSetup (ScreenPtr pScreen) +{ + DamageScrPrivPtr pScrPriv; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + if (damageGeneration != serverGeneration) + { + damageScrPrivateIndex = AllocateScreenPrivateIndex (); + if (damageScrPrivateIndex == -1) + return FALSE; + damageGCPrivateIndex = AllocateGCPrivateIndex (); + if (damageGCPrivateIndex == -1) + return FALSE; + damagePixPrivateIndex = AllocatePixmapPrivateIndex (); + if (damagePixPrivateIndex == -1) + return FALSE; + damageWinPrivateIndex = AllocateWindowPrivateIndex (); + if (damageWinPrivateIndex == -1) + return FALSE; + damageGeneration = serverGeneration; + } + if (pScreen->devPrivates[damageScrPrivateIndex].ptr) + return TRUE; + + if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec))) + return FALSE; + if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0)) + return FALSE; + if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0)) + return FALSE; + + pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec)); + if (!pScrPriv) + return FALSE; + +#ifdef COMPOSITE + /* This is a kludge to ensure wrapping order with the composite wrapper. + * If it's done from compinit.c, then DamageSetup may be called before the + * extension init phase, so that cw will be higher in the wrapping chain and + * rewrite drawables before damage gets to it, causing confusion. + */ + if (!noCompositeExtension) + miInitializeCompositeWrapper (pScreen); +#endif + + pScrPriv->internalLevel = 0; + pScrPriv->pScreenDamage = 0; + + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); + wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +#ifdef RENDER + if (ps) { + wrap (pScrPriv, ps, Glyphs, damageGlyphs); + wrap (pScrPriv, ps, Composite, damageComposite); + } +#endif + + pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv; + return TRUE; +} + +DamagePtr +DamageCreate (DamageReportFunc damageReport, + DamageDestroyFunc damageDestroy, + DamageReportLevel damageLevel, + Bool isInternal, + ScreenPtr pScreen, + void *closure) +{ + DamagePtr pDamage; + + pDamage = xalloc (sizeof (DamageRec)); + if (!pDamage) + return 0; + pDamage->pNext = 0; + pDamage->pNextWin = 0; + REGION_NULL(pScreen, &pDamage->damage); + + pDamage->damageLevel = damageLevel; + pDamage->isInternal = isInternal; + pDamage->closure = closure; + pDamage->isWindow = FALSE; + pDamage->pDrawable = 0; + + pDamage->damageReport = damageReport; + pDamage->damageDestroy = damageDestroy; + return pDamage; +} + +void +DamageRegister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef(pWindow); + +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) + if (pOld == pDamage) { + ErrorF ("Damage already on window list\n"); + abort (); + } +#endif + pDamage->pNextWin = *pPrev; + *pPrev = pDamage; + pDamage->isWindow = TRUE; + } + else + pDamage->isWindow = FALSE; + pDamage->pDrawable = pDrawable; + damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDrawInternal (ScreenPtr pScreen, Bool enable) +{ + damageScrPriv (pScreen); + + pScrPriv->internalLevel += enable ? 1 : -1; +} + +void +DamageUnregister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef (pWindow); +#if DAMAGE_VALIDATE_ENABLE + int found = 0; +#endif + + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNextWin; +#if DAMAGE_VALIDATE_ENABLE + found = 1; +#endif + break; + } + pPrev = &(*pPrev)->pNextWin; + } +#if DAMAGE_VALIDATE_ENABLE + if (!found) { + ErrorF ("Damage not on window list\n"); + abort (); + } +#endif + } + pDamage->pDrawable = 0; + damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDestroy (DamagePtr pDamage) +{ + if (pDamage->damageDestroy) + (*pDamage->damageDestroy) (pDamage, pDamage->closure); + REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage); + xfree (pDamage); +} + +Bool +DamageSubtract (DamagePtr pDamage, + const RegionPtr pRegion) +{ + RegionPtr pClip; + RegionRec pixmapClip; + DrawablePtr pDrawable = pDamage->pDrawable; + + REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion); + if (pDrawable) + { + if (pDrawable->type == DRAWABLE_WINDOW) + pClip = &((WindowPtr) pDrawable)->borderClip; + else + { + BoxRec box; + + box.x1 = pDrawable->x; + box.y1 = pDrawable->y; + box.x2 = pDrawable->x + pDrawable->width; + box.y2 = pDrawable->y + pDrawable->height; + REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1); + pClip = &pixmapClip; + } + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y); + REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip); + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y); + if (pDrawable->type != DRAWABLE_WINDOW) + REGION_UNINIT(pDrawable->pScreen, &pixmapClip); + } + return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage); +} + +void +DamageEmpty (DamagePtr pDamage) +{ + REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage); +} + +RegionPtr +DamageRegion (DamagePtr pDamage) +{ + return &pDamage->damage; +} + +void +DamageDamageRegion (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + damageDamageRegion (pDrawable, pRegion, FALSE, -1); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.NX.original new file mode 100644 index 000000000..c49f1587f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.NX.original @@ -0,0 +1,2073 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $Id: damage.c,v 1.19 2005/10/06 21:55:41 anholt Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "damage.h" +#include "damagestr.h" +#ifdef COMPOSITE +#include "cw.h" +#endif + +#define wrap(priv, real, mem, func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +#define BOX_SAME(a,b) \ + ((a)->x1 == (b)->x1 && \ + (a)->y1 == (b)->y1 && \ + (a)->x2 == (b)->x2 && \ + (a)->y2 == (b)->y2) + +#define DAMAGE_VALIDATE_ENABLE 0 +#define DAMAGE_DEBUG_ENABLE 0 +#if DAMAGE_DEBUG_ENABLE +#define DAMAGE_DEBUG(x) ErrorF x +#else +#define DAMAGE_DEBUG(x) +#endif + +#define getPixmapDamageRef(pPixmap) \ + ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr)) + +#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) + +static DamagePtr * +getDrawableDamageRef (DrawablePtr pDrawable) +{ + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW) + { + ScreenPtr pScreen = pDrawable->pScreen; + + pPixmap = 0; + if (pScreen->GetWindowPixmap +#ifdef ROOTLESS_WORKAROUND + && ((WindowPtr)pDrawable)->viewable +#endif + ) + pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable); + + if (!pPixmap) + { + damageScrPriv(pScreen); + + return &pScrPriv->pScreenDamage; + } + } + else + pPixmap = (PixmapPtr) pDrawable; + return getPixmapDamageRef (pPixmap); +} + +#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable)) +#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable) + +#define drawableDamage(pDrawable) \ + DamagePtr pDamage = getDrawableDamage(pDrawable) + +#define windowDamage(pWin) drawableDamage(&(pWin)->drawable) + +#define winDamageRef(pWindow) \ + DamagePtr *pPrev = (DamagePtr *) \ + &(pWindow->devPrivates[damageWinPrivateIndex].ptr) + +#if DAMAGE_DEBUG_ENABLE +static void +_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) +#define damageDamageRegion(d,r,c,m) _damageDamageRegion(d,r,c,m,__FUNCTION__) +#else +static void +damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, + int subWindowMode) +#endif +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + drawableDamage(pDrawable); + DamagePtr pNext; + RegionRec clippedRec; + RegionPtr pDamageRegion; + RegionRec pixClip; + Bool was_empty; + RegionRec tmpRegion; + BoxRec tmpBox; + int draw_x, draw_y; +#ifdef COMPOSITE + int screen_x = 0, screen_y = 0; +#endif + + /* short circuit for empty regions */ + if (!REGION_NOTEMPTY(pScreen, pRegion)) + return; + +#ifdef COMPOSITE + /* + * When drawing to a pixmap which is storing window contents, + * the region presented is in pixmap relative coordinates which + * need to be converted to screen relative coordinates + */ + if (pDrawable->type != DRAWABLE_WINDOW) + { + screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; + screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; + } + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y); +#endif + + if (pDrawable->type == DRAWABLE_WINDOW && + ((WindowPtr)(pDrawable))->backingStore == NotUseful) + { + if (subWindowMode == ClipByChildren) + { + REGION_INTERSECT(pScreen, pRegion, pRegion, + &((WindowPtr)(pDrawable))->clipList); + } + else if (subWindowMode == IncludeInferiors) + { + RegionPtr pTempRegion = + NotClippedByChildren((WindowPtr)(pDrawable)); + REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); + REGION_DESTROY(pScreen, pTempRegion); + } + /* If subWindowMode is set to an invalid value, don't perform + * any drawable-based clipping. */ + } + + + REGION_NULL (pScreen, &clippedRec); + for (; pDamage; pDamage = pNext) + { + pNext = pDamage->pNext; + /* + * Check for internal damage and don't send events + */ + if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) + { + DAMAGE_DEBUG (("non internal damage, skipping at %d\n", + pScrPriv->internalLevel)); + continue; + } + /* + * Check for unrealized windows + */ + if (pDamage->pDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr) (pDamage->pDrawable))->realized) + { +#if 0 + DAMAGE_DEBUG (("damage while window unrealized\n")); +#endif + continue; + } + + draw_x = pDamage->pDrawable->x; + draw_y = pDamage->pDrawable->y; +#ifdef COMPOSITE + /* + * Need to move everyone to screen coordinates + * XXX what about off-screen pixmaps with non-zero x/y? + */ + if (pDamage->pDrawable->type != DRAWABLE_WINDOW) + { + draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x; + draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y; + } +#endif + + /* + * Clip against border or pixmap bounds + */ + + pDamageRegion = pRegion; + if (clip || pDamage->pDrawable != pDrawable) + { + pDamageRegion = &clippedRec; + if (pDamage->pDrawable->type == DRAWABLE_WINDOW) { + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, + &((WindowPtr)(pDamage->pDrawable))->borderClip); + } else { + BoxRec box; + box.x1 = draw_x; + box.y1 = draw_y; + box.x2 = draw_x + pDamage->pDrawable->width; + box.y2 = draw_y + pDamage->pDrawable->height; + REGION_INIT(pScreen, &pixClip, &box, 1); + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip); + REGION_UNINIT(pScreen, &pixClip); + } + /* + * Short circuit empty results + */ + if (!REGION_NOTEMPTY(pScreen, pDamageRegion)) + continue; + } + + DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n", + where, + pDamageRegion->extents.x2 - pDamageRegion->extents.x1, + pDamageRegion->extents.y2 - pDamageRegion->extents.y1, + pDamageRegion->extents.x1, pDamageRegion->extents.y1, + pDrawable->id, pDamage->pDrawable->id)); + + /* + * Move region to target coordinate space + */ + if (draw_x || draw_y) + REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + REGION_NULL (pScreen, &tmpRegion); + REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage); + if (REGION_NOTEMPTY (pScreen, &tmpRegion)) + { + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); + } + REGION_UNINIT(pScreen, &tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNonEmpty: + was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNone: + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + break; + } + /* + * translate original region back + */ + if (pDamageRegion == pRegion && (draw_x || draw_y)) + REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y); + } +#ifdef COMPOSITE + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y); +#endif + + REGION_UNINIT (pScreen, &clippedRec); +} + +#if DAMAGE_DEBUG_ENABLE +#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) +static void +_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where) +#else +static void +damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) +#endif +{ + RegionRec region; + + REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1); +#if DAMAGE_DEBUG_ENABLE + _damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode, where); +#else + damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode); +#endif + REGION_UNINIT (pDrawable->pScreen, ®ion); +} + +static void damageValidateGC(GCPtr, unsigned long, DrawablePtr); +static void damageChangeGC(GCPtr, unsigned long); +static void damageCopyGC(GCPtr, unsigned long, GCPtr); +static void damageDestroyGC(GCPtr); +static void damageChangeClip(GCPtr, int, pointer, int); +static void damageDestroyClip(GCPtr); +static void damageCopyClip(GCPtr, GCPtr); + +GCFuncs damageGCFuncs = { + damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, + damageChangeClip, damageDestroyClip, damageCopyClip +}; + +extern GCOps damageGCOps; + +static Bool +damageCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + damageScrPriv(pScreen); + damageGCPriv(pGC); + Bool ret; + + pGC->pCompositeClip = 0; + unwrap (pScrPriv, pScreen, CreateGC); + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; + } + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + + return ret; +} + +#ifdef NOTUSED +static void +damageWrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; +} + +static void +damageUnwrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGC->funcs = pGCPriv->funcs; + if (pGCPriv->ops) + pGC->ops = pGCPriv->ops; +} +#endif + +#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ + damageGCPriv(pGC); \ + GCFuncs *oldFuncs = pGC->funcs; \ + unwrap(pGCPriv, pGC, funcs); \ + unwrap(pGCPriv, pGC, ops); \ + +#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \ + wrap(pGCPriv, pGC, funcs, oldFuncs); \ + wrap(pGCPriv, pGC, ops, &damageGCOps) + +#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \ + damageGCPriv(pGC); \ + unwrap(pGCPriv, pGC, funcs); \ + if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) + +#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \ + wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \ + if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps) + +static void +damageValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDrawable) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageDestroyGC(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageChangeGC (GCPtr pGC, + unsigned long mask) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + DAMAGE_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +damageChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + DAMAGE_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + DAMAGE_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +damageDestroyClip(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ + BoxPtr extents = &pGC->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define TRANSLATE_BOX(box, pDrawable) { \ + box.x1 += pDrawable->x; \ + box.x2 += pDrawable->x; \ + box.y1 += pDrawable->y; \ + box.y2 += pDrawable->y; \ + } + +#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ + TRANSLATE_BOX(box, pDrawable); \ + TRIM_BOX(box, pGC); \ + } + +#define BOX_NOT_EMPTY(box) \ + (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) + +#define checkGCDamage(d,g) (getDrawableDamage(d) && \ + (!g->pCompositeClip ||\ + REGION_NOTEMPTY(d->pScreen, \ + g->pCompositeClip))) + +#ifdef RENDER + +#define TRIM_PICTURE_BOX(box, pDst) { \ + BoxPtr extents = &pDst->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \ + REGION_NOTEMPTY(pScreen, p->pCompositeClip)) + +static void +damageComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + BoxRec box; + + box.x1 = xDst + pDst->pDrawable->x; + box.y1 = yDst + pDst->pDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + TRIM_PICTURE_BOX(box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + wrap (pScrPriv, ps, Composite, damageComposite); +} + +static void +damageGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + int nlistTmp = nlist; + GlyphListPtr listTmp = list; + GlyphPtr *glyphsTmp = glyphs; + int x, y; + int n; + GlyphPtr glyph; + BoxRec box; + int x1, y1, x2, y2; + + box.x1 = 32767; + box.y1 = 32767; + box.x2 = -32767; + box.y2 = -32767; + x = pDst->pDrawable->x; + y = pDst->pDrawable->y; + while (nlistTmp--) + { + x += listTmp->xOff; + y += listTmp->yOff; + n = listTmp->len; + while (n--) + { + glyph = *glyphsTmp++; + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + if (x1 < box.x1) + box.x1 = x1; + if (y1 < box.y1) + box.y1 = y1; + if (x2 > box.x2) + box.x2 = x2; + if (y2 > box.y2) + box.y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + listTmp++; + } + TRIM_PICTURE_BOX (box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + wrap (pScrPriv, ps, Glyphs, damageGlyphs); +} +#endif + +/**********************************************************/ + + +static void +damageFillSpans(DrawablePtr pDrawable, + GC *pGC, + int npt, + DDXPointPtr ppt, + int *pwidth, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageSetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr ppt, + int *pwidth, + int npt, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + int nptTmp = npt; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = x + pDrawable->x; + box.x2 = box.x1 + w; + box.y1 = y + pDrawable->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, + leftPad, format, pImage); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static RegionPtr +damageCopyArea(DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && + pSrc->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + } + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static RegionPtr +damageCopyPlane(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long bitPlane) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && + pSrc->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + } + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static void +damagePolyPoint(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + xPoint *ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nptTmp = npt; + xPoint *pptTmp = ppt; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + /* this could be slow if the points were spread out */ + + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolylines(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(nptTmp > 1) + { + if(pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if(pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if(mode == CoordModePrevious) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolySegment(DrawablePtr pDrawable, + GCPtr pGC, + int nSeg, + xSegment *pSeg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nSeg && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int extra = pGC->lineWidth; + int nsegTmp = nSeg; + xSegment *pSegTmp = pSeg; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSegTmp->x2 > pSegTmp->x1) { + box.x1 = pSegTmp->x1; + box.x2 = pSegTmp->x2; + } else { + box.x2 = pSegTmp->x1; + box.x1 = pSegTmp->x2; + } + + if(pSegTmp->y2 > pSegTmp->y1) { + box.y1 = pSegTmp->y1; + box.y2 = pSegTmp->y2; + } else { + box.y2 = pSegTmp->y1; + box.y1 = pSegTmp->y2; + } + + while(--nsegTmp) + { + pSegTmp++; + if(pSegTmp->x2 > pSegTmp->x1) + { + if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; + if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; + } + else + { + if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; + if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; + } + if(pSegTmp->y2 > pSegTmp->y1) + { + if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; + if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; + } + else + { + if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; + if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyRectangle(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int offset1, offset2, offset3; + int nRectsTmp = nRects; + xRectangle *pRectsTmp = pRects; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while(nRectsTmp--) + { + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + pRectsTmp++; + } + } + (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + int extra = pGC->lineWidth >> 1; + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageFillPolygon(DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt > 2 && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int nptTmp = npt; + BoxRec box; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(mode != CoordModeOrigin) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + xRectangle *pRectsTmp = pRects; + int nRectsTmp = nRects; + + box.x1 = pRectsTmp->x; + box.x2 = box.x1 + pRectsTmp->width; + box.y1 = pRectsTmp->y; + box.y2 = box.y1 + pRectsTmp->height; + + while(--nRectsTmp) + { + pRectsTmp++; + if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x; + if(box.x2 < (pRectsTmp->x + pRectsTmp->width)) + box.x2 = pRectsTmp->x + pRectsTmp->width; + if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y; + if(box.y2 < (pRectsTmp->y + pRectsTmp->height)) + box.y2 = pRectsTmp->y + pRectsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +/* + * general Poly/Image text function. Extract glyph information, + * compute bounding box and remove cursor if it is overlapped. + */ + +static void +damageDamageChars (DrawablePtr pDrawable, + FontPtr font, + int x, + int y, + unsigned int n, + CharInfoPtr *charinfo, + Bool imageblt, + int subWindowMode) +{ + ExtentInfoRec extents; + BoxRec box; + + QueryGlyphExtents(font, charinfo, n, &extents); + if (imageblt) + { + if (extents.overallWidth > extents.overallRight) + extents.overallRight = extents.overallWidth; + if (extents.overallWidth < extents.overallLeft) + extents.overallLeft = extents.overallWidth; + if (extents.overallLeft > 0) + extents.overallLeft = 0; + if (extents.fontAscent > extents.overallAscent) + extents.overallAscent = extents.fontAscent; + if (extents.fontDescent > extents.overallDescent) + extents.overallDescent = extents.fontDescent; + } + box.x1 = x + extents.overallLeft; + box.y1 = y - extents.overallAscent; + box.x2 = x + extents.overallRight; + box.y2 = y + extents.overallDescent; + damageDamageBox (pDrawable, &box, subWindowMode); +} + +/* + * values for textType: + */ +#define TT_POLY8 0 +#define TT_IMAGE8 1 +#define TT_POLY16 2 +#define TT_IMAGE16 3 + +static int +damageText (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned long count, + char *chars, + FontEncoding fontEncoding, + Bool textType) +{ + CharInfoPtr *charinfo; + CharInfoPtr *info; + unsigned long i; + unsigned int n; + int w; + Bool imageblt; + + imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); + + charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); + if (!charinfo) + return x; + + GetGlyphs(pGC->font, count, (unsigned char *)chars, + fontEncoding, &i, charinfo); + n = (unsigned int)i; + w = 0; + if (!imageblt) + for (info = charinfo; i--; info++) + w += (*info)->metrics.characterWidth; + + if (n != 0) { + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, + charinfo, imageblt, pGC->subWindowMode); + +#ifndef NXAGENT_SERVER + + if (imageblt) + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + else + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); +#endif + + } + DEALLOCATE_LOCAL(charinfo); + return x + w; +} + +#ifndef NXAGENT_SERVER + +static int +damagePolyText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + else + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static int +damagePolyText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_POLY16); + else + x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static void +damageImageText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_IMAGE8); + else + (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageImageText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_IMAGE16); + else + (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +#else /* #ifndef NXAGENT_SERVER */ + +static int +damagePolyText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static int +damagePolyText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_POLY16); + + x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static void +damageImageText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_IMAGE8); + + (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageImageText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_IMAGE16); + + (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +#endif /* #ifndef NXAGENT_SERVER */ + +static void +damageImageGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, TRUE, pGC->subWindowMode); + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, FALSE, pGC->subWindowMode); + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePushPixels(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if(checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = xOrg; + box.y1 = yOrg; + + if(!pGC->miTranslate) { + box.x1 += pDrawable->x; + box.y1 += pDrawable->y; + } + + box.x2 = box.x1 + dx; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNext; + return; + } + pPrev = &(*pPrev)->pNext; + } +#if DAMAGE_VALIDATE_ENABLE + ErrorF ("Damage not on list\n"); + abort (); +#endif +} + +static void +damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNext) + if (pOld == pDamage) { + ErrorF ("Damage already on list\n"); + abort (); + } +#endif + pDamage->pNext = *pPrev; + *pPrev = pDamage; +} + +static Bool +damageDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + damageScrPriv(pScreen); + + if (pPixmap->refcnt == 1) + { + DamagePtr *pPrev = getPixmapDamageRef (pPixmap); + DamagePtr pDamage; + + while ((pDamage = *pPrev)) + { + damageRemoveDamage (pPrev, pDamage); + if (!pDamage->isWindow) + DamageDestroy (pDamage); + } + } + unwrap (pScrPriv, pScreen, DestroyPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + return TRUE; +} + +static void +damagePaintWindow(WindowPtr pWindow, + RegionPtr prgn, + int what) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + /* + * Painting background none doesn't actually *do* anything, so + * no damage is recorded + */ + if ((what != PW_BACKGROUND || pWindow->backgroundState != None) && + getWindowDamage (pWindow)) + damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); + if(what == PW_BACKGROUND) { + unwrap (pScrPriv, pScreen, PaintWindowBackground); + (*pScreen->PaintWindowBackground) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + } else { + unwrap (pScrPriv, pScreen, PaintWindowBorder); + (*pScreen->PaintWindowBorder) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + } +} + + +static void +damageCopyWindow(WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if (getWindowDamage (pWindow)) + { + int dx = pWindow->drawable.x - ptOldOrg.x; + int dy = pWindow->drawable.y - ptOldOrg.y; + + /* + * The region comes in source relative, but the damage occurs + * at the destination location. Translate back and forth. + */ + REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); + damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1); + REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); + } + unwrap (pScrPriv, pScreen, CopyWindow); + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); +} + +GCOps damageGCOps = { + damageFillSpans, damageSetSpans, + damagePutImage, damageCopyArea, + damageCopyPlane, damagePolyPoint, + damagePolylines, damagePolySegment, + damagePolyRectangle, damagePolyArc, + damageFillPolygon, damagePolyFillRect, + damagePolyFillArc, damagePolyText8, + damagePolyText16, damageImageText8, + damageImageText16, damageImageGlyphBlt, + damagePolyGlyphBlt, damagePushPixels, +#ifdef NEED_LINEHELPER + NULL, +#endif + {NULL} /* devPrivate */ +}; + +static void +damageRestoreAreas (PixmapPtr pPixmap, + RegionPtr prgn, + int xorg, + int yorg, + WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, + xorg, yorg, pWindow); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +} + +static void +damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if ((pDamage = damageGetWinPriv(pWindow))) + { + PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow); + DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap); + + while (pDamage) + { + damageRemoveDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } + unwrap (pScrPriv, pScreen, SetWindowPixmap); + (*pScreen->SetWindowPixmap) (pWindow, pPixmap); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + if ((pDamage = damageGetWinPriv(pWindow))) + { + DamagePtr *pPrev = getPixmapDamageRef(pPixmap); + + while (pDamage) + { + damageInsertDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } +} + +static Bool +damageDestroyWindow (WindowPtr pWindow) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + Bool ret; + damageScrPriv(pScreen); + + while ((pDamage = damageGetWinPriv(pWindow))) + { + DamageUnregister (&pWindow->drawable, pDamage); + DamageDestroy (pDamage); + } + unwrap (pScrPriv, pScreen, DestroyWindow); + ret = (*pScreen->DestroyWindow) (pWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + return ret; +} + +static Bool +damageCloseScreen (int i, ScreenPtr pScreen) +{ + damageScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, DestroyPixmap); + unwrap (pScrPriv, pScreen, CreateGC); + unwrap (pScrPriv, pScreen, PaintWindowBackground); + unwrap (pScrPriv, pScreen, PaintWindowBorder); + unwrap (pScrPriv, pScreen, CopyWindow); + unwrap (pScrPriv, pScreen, CloseScreen); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + xfree (pScrPriv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +int damageScrPrivateIndex; +int damagePixPrivateIndex; +int damageGCPrivateIndex; +int damageWinPrivateIndex; +int damageGeneration; + +Bool +DamageSetup (ScreenPtr pScreen) +{ + DamageScrPrivPtr pScrPriv; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + if (damageGeneration != serverGeneration) + { + damageScrPrivateIndex = AllocateScreenPrivateIndex (); + if (damageScrPrivateIndex == -1) + return FALSE; + damageGCPrivateIndex = AllocateGCPrivateIndex (); + if (damageGCPrivateIndex == -1) + return FALSE; + damagePixPrivateIndex = AllocatePixmapPrivateIndex (); + if (damagePixPrivateIndex == -1) + return FALSE; + damageWinPrivateIndex = AllocateWindowPrivateIndex (); + if (damageWinPrivateIndex == -1) + return FALSE; + damageGeneration = serverGeneration; + } + if (pScreen->devPrivates[damageScrPrivateIndex].ptr) + return TRUE; + + if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec))) + return FALSE; + if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0)) + return FALSE; + if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0)) + return FALSE; + + pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec)); + if (!pScrPriv) + return FALSE; + +#ifdef COMPOSITE + /* This is a kludge to ensure wrapping order with the composite wrapper. + * If it's done from compinit.c, then DamageSetup may be called before the + * extension init phase, so that cw will be higher in the wrapping chain and + * rewrite drawables before damage gets to it, causing confusion. + */ + if (!noCompositeExtension) + miInitializeCompositeWrapper (pScreen); +#endif + + pScrPriv->internalLevel = 0; + pScrPriv->pScreenDamage = 0; + + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); + wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +#ifdef RENDER + if (ps) { + wrap (pScrPriv, ps, Glyphs, damageGlyphs); + wrap (pScrPriv, ps, Composite, damageComposite); + } +#endif + + pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv; + return TRUE; +} + +DamagePtr +DamageCreate (DamageReportFunc damageReport, + DamageDestroyFunc damageDestroy, + DamageReportLevel damageLevel, + Bool isInternal, + ScreenPtr pScreen, + void *closure) +{ + DamagePtr pDamage; + + pDamage = xalloc (sizeof (DamageRec)); + if (!pDamage) + return 0; + pDamage->pNext = 0; + pDamage->pNextWin = 0; + REGION_NULL(pScreen, &pDamage->damage); + + pDamage->damageLevel = damageLevel; + pDamage->isInternal = isInternal; + pDamage->closure = closure; + pDamage->isWindow = FALSE; + pDamage->pDrawable = 0; + + pDamage->damageReport = damageReport; + pDamage->damageDestroy = damageDestroy; + return pDamage; +} + +void +DamageRegister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef(pWindow); + +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) + if (pOld == pDamage) { + ErrorF ("Damage already on window list\n"); + abort (); + } +#endif + pDamage->pNextWin = *pPrev; + *pPrev = pDamage; + pDamage->isWindow = TRUE; + } + else + pDamage->isWindow = FALSE; + pDamage->pDrawable = pDrawable; + damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDrawInternal (ScreenPtr pScreen, Bool enable) +{ + damageScrPriv (pScreen); + + pScrPriv->internalLevel += enable ? 1 : -1; +} + +void +DamageUnregister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef (pWindow); +#if DAMAGE_VALIDATE_ENABLE + int found = 0; +#endif + + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNextWin; +#if DAMAGE_VALIDATE_ENABLE + found = 1; +#endif + break; + } + pPrev = &(*pPrev)->pNextWin; + } +#if DAMAGE_VALIDATE_ENABLE + if (!found) { + ErrorF ("Damage not on window list\n"); + abort (); + } +#endif + } + pDamage->pDrawable = 0; + damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDestroy (DamagePtr pDamage) +{ + if (pDamage->damageDestroy) + (*pDamage->damageDestroy) (pDamage, pDamage->closure); + REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage); + xfree (pDamage); +} + +Bool +DamageSubtract (DamagePtr pDamage, + const RegionPtr pRegion) +{ + RegionPtr pClip; + RegionRec pixmapClip; + DrawablePtr pDrawable = pDamage->pDrawable; + + REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion); + if (pDrawable) + { + if (pDrawable->type == DRAWABLE_WINDOW) + pClip = &((WindowPtr) pDrawable)->borderClip; + else + { + BoxRec box; + + box.x1 = pDrawable->x; + box.y1 = pDrawable->y; + box.x2 = pDrawable->x + pDrawable->width; + box.y2 = pDrawable->y + pDrawable->height; + REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1); + pClip = &pixmapClip; + } + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y); + REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip); + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y); + if (pDrawable->type != DRAWABLE_WINDOW) + REGION_UNINIT(pDrawable->pScreen, &pixmapClip); + } + return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage); +} + +void +DamageEmpty (DamagePtr pDamage) +{ + REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage); +} + +RegionPtr +DamageRegion (DamagePtr pDamage) +{ + return &pDamage->damage; +} + +void +DamageDamageRegion (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + damageDamageRegion (pDrawable, pRegion, FALSE, -1); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.X.original new file mode 100644 index 000000000..286728cd1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.X.original @@ -0,0 +1,1966 @@ +/* + * $Id: damage.c,v 1.19 2005/10/06 21:55:41 anholt Exp $ + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "damage.h" +#include "damagestr.h" +#ifdef COMPOSITE +#include "cw.h" +#endif + +#define wrap(priv, real, mem, func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +#define BOX_SAME(a,b) \ + ((a)->x1 == (b)->x1 && \ + (a)->y1 == (b)->y1 && \ + (a)->x2 == (b)->x2 && \ + (a)->y2 == (b)->y2) + +#define DAMAGE_VALIDATE_ENABLE 0 +#define DAMAGE_DEBUG_ENABLE 0 +#if DAMAGE_DEBUG_ENABLE +#define DAMAGE_DEBUG(x) ErrorF x +#else +#define DAMAGE_DEBUG(x) +#endif + +#define getPixmapDamageRef(pPixmap) \ + ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr)) + +#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) + +static DamagePtr * +getDrawableDamageRef (DrawablePtr pDrawable) +{ + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW) + { + ScreenPtr pScreen = pDrawable->pScreen; + + pPixmap = 0; + if (pScreen->GetWindowPixmap +#ifdef ROOTLESS_WORKAROUND + && ((WindowPtr)pDrawable)->viewable +#endif + ) + pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable); + + if (!pPixmap) + { + damageScrPriv(pScreen); + + return &pScrPriv->pScreenDamage; + } + } + else + pPixmap = (PixmapPtr) pDrawable; + return getPixmapDamageRef (pPixmap); +} + +#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable)) +#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable) + +#define drawableDamage(pDrawable) \ + DamagePtr pDamage = getDrawableDamage(pDrawable) + +#define windowDamage(pWin) drawableDamage(&(pWin)->drawable) + +#define winDamageRef(pWindow) \ + DamagePtr *pPrev = (DamagePtr *) \ + &(pWindow->devPrivates[damageWinPrivateIndex].ptr) + +#if DAMAGE_DEBUG_ENABLE +static void +_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) +#define damageDamageRegion(d,r,c,m) _damageDamageRegion(d,r,c,m,__FUNCTION__) +#else +static void +damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, + int subWindowMode) +#endif +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + drawableDamage(pDrawable); + DamagePtr pNext; + RegionRec clippedRec; + RegionPtr pDamageRegion; + RegionRec pixClip; + Bool was_empty; + RegionRec tmpRegion; + BoxRec tmpBox; + int draw_x, draw_y; +#ifdef COMPOSITE + int screen_x = 0, screen_y = 0; +#endif + + /* short circuit for empty regions */ + if (!REGION_NOTEMPTY(pScreen, pRegion)) + return; + +#ifdef COMPOSITE + /* + * When drawing to a pixmap which is storing window contents, + * the region presented is in pixmap relative coordinates which + * need to be converted to screen relative coordinates + */ + if (pDrawable->type != DRAWABLE_WINDOW) + { + screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; + screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; + } + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y); +#endif + + if (pDrawable->type == DRAWABLE_WINDOW && + ((WindowPtr)(pDrawable))->backingStore == NotUseful) + { + if (subWindowMode == ClipByChildren) + { + REGION_INTERSECT(pScreen, pRegion, pRegion, + &((WindowPtr)(pDrawable))->clipList); + } + else if (subWindowMode == IncludeInferiors) + { + RegionPtr pTempRegion = + NotClippedByChildren((WindowPtr)(pDrawable)); + REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); + REGION_DESTROY(pScreen, pTempRegion); + } + /* If subWindowMode is set to an invalid value, don't perform + * any drawable-based clipping. */ + } + + + REGION_NULL (pScreen, &clippedRec); + for (; pDamage; pDamage = pNext) + { + pNext = pDamage->pNext; + /* + * Check for internal damage and don't send events + */ + if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) + { + DAMAGE_DEBUG (("non internal damage, skipping at %d\n", + pScrPriv->internalLevel)); + continue; + } + /* + * Check for unrealized windows + */ + if (pDamage->pDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr) (pDamage->pDrawable))->realized) + { +#if 0 + DAMAGE_DEBUG (("damage while window unrealized\n")); +#endif + continue; + } + + draw_x = pDamage->pDrawable->x; + draw_y = pDamage->pDrawable->y; +#ifdef COMPOSITE + /* + * Need to move everyone to screen coordinates + * XXX what about off-screen pixmaps with non-zero x/y? + */ + if (pDamage->pDrawable->type != DRAWABLE_WINDOW) + { + draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x; + draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y; + } +#endif + + /* + * Clip against border or pixmap bounds + */ + + pDamageRegion = pRegion; + if (clip || pDamage->pDrawable != pDrawable) + { + pDamageRegion = &clippedRec; + if (pDamage->pDrawable->type == DRAWABLE_WINDOW) { + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, + &((WindowPtr)(pDamage->pDrawable))->borderClip); + } else { + BoxRec box; + box.x1 = draw_x; + box.y1 = draw_y; + box.x2 = draw_x + pDamage->pDrawable->width; + box.y2 = draw_y + pDamage->pDrawable->height; + REGION_INIT(pScreen, &pixClip, &box, 1); + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip); + REGION_UNINIT(pScreen, &pixClip); + } + /* + * Short circuit empty results + */ + if (!REGION_NOTEMPTY(pScreen, pDamageRegion)) + continue; + } + + DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n", + where, + pDamageRegion->extents.x2 - pDamageRegion->extents.x1, + pDamageRegion->extents.y2 - pDamageRegion->extents.y1, + pDamageRegion->extents.x1, pDamageRegion->extents.y1, + pDrawable->id, pDamage->pDrawable->id)); + + /* + * Move region to target coordinate space + */ + if (draw_x || draw_y) + REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + REGION_NULL (pScreen, &tmpRegion); + REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage); + if (REGION_NOTEMPTY (pScreen, &tmpRegion)) + { + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); + } + REGION_UNINIT(pScreen, &tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNonEmpty: + was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNone: + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + break; + } + /* + * translate original region back + */ + if (pDamageRegion == pRegion && (draw_x || draw_y)) + REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y); + } +#ifdef COMPOSITE + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y); +#endif + + REGION_UNINIT (pScreen, &clippedRec); +} + +#if DAMAGE_DEBUG_ENABLE +#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) +static void +_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where) +#else +static void +damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) +#endif +{ + RegionRec region; + + REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1); +#if DAMAGE_DEBUG_ENABLE + _damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode, where); +#else + damageDamageRegion (pDrawable, ®ion, TRUE, subWindowMode); +#endif + REGION_UNINIT (pDrawable->pScreen, ®ion); +} + +static void damageValidateGC(GCPtr, unsigned long, DrawablePtr); +static void damageChangeGC(GCPtr, unsigned long); +static void damageCopyGC(GCPtr, unsigned long, GCPtr); +static void damageDestroyGC(GCPtr); +static void damageChangeClip(GCPtr, int, pointer, int); +static void damageDestroyClip(GCPtr); +static void damageCopyClip(GCPtr, GCPtr); + +GCFuncs damageGCFuncs = { + damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, + damageChangeClip, damageDestroyClip, damageCopyClip +}; + +extern GCOps damageGCOps; + +static Bool +damageCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + damageScrPriv(pScreen); + damageGCPriv(pGC); + Bool ret; + + pGC->pCompositeClip = 0; + unwrap (pScrPriv, pScreen, CreateGC); + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; + } + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + + return ret; +} + +#ifdef NOTUSED +static void +damageWrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; +} + +static void +damageUnwrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGC->funcs = pGCPriv->funcs; + if (pGCPriv->ops) + pGC->ops = pGCPriv->ops; +} +#endif + +#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ + damageGCPriv(pGC); \ + GCFuncs *oldFuncs = pGC->funcs; \ + unwrap(pGCPriv, pGC, funcs); \ + unwrap(pGCPriv, pGC, ops); \ + +#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \ + wrap(pGCPriv, pGC, funcs, oldFuncs); \ + wrap(pGCPriv, pGC, ops, &damageGCOps) + +#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \ + damageGCPriv(pGC); \ + unwrap(pGCPriv, pGC, funcs); \ + if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) + +#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \ + wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \ + if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps) + +static void +damageValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDrawable) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageDestroyGC(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageChangeGC (GCPtr pGC, + unsigned long mask) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + DAMAGE_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +damageChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + DAMAGE_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + DAMAGE_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +damageDestroyClip(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ + BoxPtr extents = &pGC->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define TRANSLATE_BOX(box, pDrawable) { \ + box.x1 += pDrawable->x; \ + box.x2 += pDrawable->x; \ + box.y1 += pDrawable->y; \ + box.y2 += pDrawable->y; \ + } + +#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ + TRANSLATE_BOX(box, pDrawable); \ + TRIM_BOX(box, pGC); \ + } + +#define BOX_NOT_EMPTY(box) \ + (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) + +#define checkGCDamage(d,g) (getDrawableDamage(d) && \ + (!g->pCompositeClip ||\ + REGION_NOTEMPTY(d->pScreen, \ + g->pCompositeClip))) + +#ifdef RENDER + +#define TRIM_PICTURE_BOX(box, pDst) { \ + BoxPtr extents = &pDst->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \ + REGION_NOTEMPTY(pScreen, p->pCompositeClip)) + +static void +damageComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + BoxRec box; + + box.x1 = xDst + pDst->pDrawable->x; + box.y1 = yDst + pDst->pDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + TRIM_PICTURE_BOX(box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + wrap (pScrPriv, ps, Composite, damageComposite); +} + +static void +damageGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + int nlistTmp = nlist; + GlyphListPtr listTmp = list; + GlyphPtr *glyphsTmp = glyphs; + int x, y; + int n; + GlyphPtr glyph; + BoxRec box; + int x1, y1, x2, y2; + + box.x1 = 32767; + box.y1 = 32767; + box.x2 = -32767; + box.y2 = -32767; + x = pDst->pDrawable->x; + y = pDst->pDrawable->y; + while (nlistTmp--) + { + x += listTmp->xOff; + y += listTmp->yOff; + n = listTmp->len; + while (n--) + { + glyph = *glyphsTmp++; + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + if (x1 < box.x1) + box.x1 = x1; + if (y1 < box.y1) + box.y1 = y1; + if (x2 > box.x2) + box.x2 = x2; + if (y2 > box.y2) + box.y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + listTmp++; + } + TRIM_PICTURE_BOX (box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + wrap (pScrPriv, ps, Glyphs, damageGlyphs); +} +#endif + +/**********************************************************/ + + +static void +damageFillSpans(DrawablePtr pDrawable, + GC *pGC, + int npt, + DDXPointPtr ppt, + int *pwidth, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageSetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr ppt, + int *pwidth, + int npt, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + int nptTmp = npt; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = x + pDrawable->x; + box.x2 = box.x1 + w; + box.y1 = y + pDrawable->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, + leftPad, format, pImage); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static RegionPtr +damageCopyArea(DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && + pSrc->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + } + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static RegionPtr +damageCopyPlane(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long bitPlane) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate && + pSrc->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + } + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static void +damagePolyPoint(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + xPoint *ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nptTmp = npt; + xPoint *pptTmp = ppt; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + /* this could be slow if the points were spread out */ + + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolylines(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(nptTmp > 1) + { + if(pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if(pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if(mode == CoordModePrevious) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolySegment(DrawablePtr pDrawable, + GCPtr pGC, + int nSeg, + xSegment *pSeg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nSeg && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int extra = pGC->lineWidth; + int nsegTmp = nSeg; + xSegment *pSegTmp = pSeg; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSegTmp->x2 > pSegTmp->x1) { + box.x1 = pSegTmp->x1; + box.x2 = pSegTmp->x2; + } else { + box.x2 = pSegTmp->x1; + box.x1 = pSegTmp->x2; + } + + if(pSegTmp->y2 > pSegTmp->y1) { + box.y1 = pSegTmp->y1; + box.y2 = pSegTmp->y2; + } else { + box.y2 = pSegTmp->y1; + box.y1 = pSegTmp->y2; + } + + while(--nsegTmp) + { + pSegTmp++; + if(pSegTmp->x2 > pSegTmp->x1) + { + if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; + if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; + } + else + { + if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; + if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; + } + if(pSegTmp->y2 > pSegTmp->y1) + { + if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; + if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; + } + else + { + if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; + if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyRectangle(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int offset1, offset2, offset3; + int nRectsTmp = nRects; + xRectangle *pRectsTmp = pRects; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while(nRectsTmp--) + { + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + pRectsTmp++; + } + } + (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + int extra = pGC->lineWidth >> 1; + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageFillPolygon(DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt > 2 && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int nptTmp = npt; + BoxRec box; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(mode != CoordModeOrigin) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + xRectangle *pRectsTmp = pRects; + int nRectsTmp = nRects; + + box.x1 = pRectsTmp->x; + box.x2 = box.x1 + pRectsTmp->width; + box.y1 = pRectsTmp->y; + box.y2 = box.y1 + pRectsTmp->height; + + while(--nRectsTmp) + { + pRectsTmp++; + if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x; + if(box.x2 < (pRectsTmp->x + pRectsTmp->width)) + box.x2 = pRectsTmp->x + pRectsTmp->width; + if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y; + if(box.y2 < (pRectsTmp->y + pRectsTmp->height)) + box.y2 = pRectsTmp->y + pRectsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +/* + * general Poly/Image text function. Extract glyph information, + * compute bounding box and remove cursor if it is overlapped. + */ + +static void +damageDamageChars (DrawablePtr pDrawable, + FontPtr font, + int x, + int y, + unsigned int n, + CharInfoPtr *charinfo, + Bool imageblt, + int subWindowMode) +{ + ExtentInfoRec extents; + BoxRec box; + + QueryGlyphExtents(font, charinfo, n, &extents); + if (imageblt) + { + if (extents.overallWidth > extents.overallRight) + extents.overallRight = extents.overallWidth; + if (extents.overallWidth < extents.overallLeft) + extents.overallLeft = extents.overallWidth; + if (extents.overallLeft > 0) + extents.overallLeft = 0; + if (extents.fontAscent > extents.overallAscent) + extents.overallAscent = extents.fontAscent; + if (extents.fontDescent > extents.overallDescent) + extents.overallDescent = extents.fontDescent; + } + box.x1 = x + extents.overallLeft; + box.y1 = y - extents.overallAscent; + box.x2 = x + extents.overallRight; + box.y2 = y + extents.overallDescent; + damageDamageBox (pDrawable, &box, subWindowMode); +} + +/* + * values for textType: + */ +#define TT_POLY8 0 +#define TT_IMAGE8 1 +#define TT_POLY16 2 +#define TT_IMAGE16 3 + +static int +damageText (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned long count, + char *chars, + FontEncoding fontEncoding, + Bool textType) +{ + CharInfoPtr *charinfo; + CharInfoPtr *info; + unsigned long i; + unsigned int n; + int w; + Bool imageblt; + + imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); + + charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); + if (!charinfo) + return x; + + GetGlyphs(pGC->font, count, (unsigned char *)chars, + fontEncoding, &i, charinfo); + n = (unsigned int)i; + w = 0; + if (!imageblt) + for (info = charinfo; i--; info++) + w += (*info)->metrics.characterWidth; + + if (n != 0) { + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, + charinfo, imageblt, pGC->subWindowMode); + if (imageblt) + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + else + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + } + DEALLOCATE_LOCAL(charinfo); + return x + w; +} + +static int +damagePolyText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + else + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static int +damagePolyText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_POLY16); + else + x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static void +damageImageText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_IMAGE8); + else + (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageImageText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_IMAGE16); + else + (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damageImageGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, TRUE, pGC->subWindowMode); + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, FALSE, pGC->subWindowMode); + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePushPixels(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if(checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = xOrg; + box.y1 = yOrg; + + if(!pGC->miTranslate) { + box.x1 += pDrawable->x; + box.y1 += pDrawable->y; + } + + box.x2 = box.x1 + dx; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNext; + return; + } + pPrev = &(*pPrev)->pNext; + } +#if DAMAGE_VALIDATE_ENABLE + ErrorF ("Damage not on list\n"); + abort (); +#endif +} + +static void +damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNext) + if (pOld == pDamage) { + ErrorF ("Damage already on list\n"); + abort (); + } +#endif + pDamage->pNext = *pPrev; + *pPrev = pDamage; +} + +static Bool +damageDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + damageScrPriv(pScreen); + + if (pPixmap->refcnt == 1) + { + DamagePtr *pPrev = getPixmapDamageRef (pPixmap); + DamagePtr pDamage; + + while ((pDamage = *pPrev)) + { + damageRemoveDamage (pPrev, pDamage); + if (!pDamage->isWindow) + DamageDestroy (pDamage); + } + } + unwrap (pScrPriv, pScreen, DestroyPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + return TRUE; +} + +static void +damagePaintWindow(WindowPtr pWindow, + RegionPtr prgn, + int what) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + /* + * Painting background none doesn't actually *do* anything, so + * no damage is recorded + */ + if ((what != PW_BACKGROUND || pWindow->backgroundState != None) && + getWindowDamage (pWindow)) + damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); + if(what == PW_BACKGROUND) { + unwrap (pScrPriv, pScreen, PaintWindowBackground); + (*pScreen->PaintWindowBackground) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + } else { + unwrap (pScrPriv, pScreen, PaintWindowBorder); + (*pScreen->PaintWindowBorder) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + } +} + + +static void +damageCopyWindow(WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if (getWindowDamage (pWindow)) + { + int dx = pWindow->drawable.x - ptOldOrg.x; + int dy = pWindow->drawable.y - ptOldOrg.y; + + /* + * The region comes in source relative, but the damage occurs + * at the destination location. Translate back and forth. + */ + REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); + damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE, -1); + REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); + } + unwrap (pScrPriv, pScreen, CopyWindow); + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); +} + +GCOps damageGCOps = { + damageFillSpans, damageSetSpans, + damagePutImage, damageCopyArea, + damageCopyPlane, damagePolyPoint, + damagePolylines, damagePolySegment, + damagePolyRectangle, damagePolyArc, + damageFillPolygon, damagePolyFillRect, + damagePolyFillArc, damagePolyText8, + damagePolyText16, damageImageText8, + damageImageText16, damageImageGlyphBlt, + damagePolyGlyphBlt, damagePushPixels, +#ifdef NEED_LINEHELPER + NULL, +#endif + {NULL} /* devPrivate */ +}; + +static void +damageRestoreAreas (PixmapPtr pPixmap, + RegionPtr prgn, + int xorg, + int yorg, + WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + damageDamageRegion (&pWindow->drawable, prgn, FALSE, -1); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, + xorg, yorg, pWindow); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +} + +static void +damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if ((pDamage = damageGetWinPriv(pWindow))) + { + PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow); + DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap); + + while (pDamage) + { + damageRemoveDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } + unwrap (pScrPriv, pScreen, SetWindowPixmap); + (*pScreen->SetWindowPixmap) (pWindow, pPixmap); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + if ((pDamage = damageGetWinPriv(pWindow))) + { + DamagePtr *pPrev = getPixmapDamageRef(pPixmap); + + while (pDamage) + { + damageInsertDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } +} + +static Bool +damageDestroyWindow (WindowPtr pWindow) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + Bool ret; + damageScrPriv(pScreen); + + while ((pDamage = damageGetWinPriv(pWindow))) + { + DamageUnregister (&pWindow->drawable, pDamage); + DamageDestroy (pDamage); + } + unwrap (pScrPriv, pScreen, DestroyWindow); + ret = (*pScreen->DestroyWindow) (pWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + return ret; +} + +static Bool +damageCloseScreen (int i, ScreenPtr pScreen) +{ + damageScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, DestroyPixmap); + unwrap (pScrPriv, pScreen, CreateGC); + unwrap (pScrPriv, pScreen, PaintWindowBackground); + unwrap (pScrPriv, pScreen, PaintWindowBorder); + unwrap (pScrPriv, pScreen, CopyWindow); + unwrap (pScrPriv, pScreen, CloseScreen); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + xfree (pScrPriv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +int damageScrPrivateIndex; +int damagePixPrivateIndex; +int damageGCPrivateIndex; +int damageWinPrivateIndex; +int damageGeneration; + +Bool +DamageSetup (ScreenPtr pScreen) +{ + DamageScrPrivPtr pScrPriv; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + if (damageGeneration != serverGeneration) + { + damageScrPrivateIndex = AllocateScreenPrivateIndex (); + if (damageScrPrivateIndex == -1) + return FALSE; + damageGCPrivateIndex = AllocateGCPrivateIndex (); + if (damageGCPrivateIndex == -1) + return FALSE; + damagePixPrivateIndex = AllocatePixmapPrivateIndex (); + if (damagePixPrivateIndex == -1) + return FALSE; + damageWinPrivateIndex = AllocateWindowPrivateIndex (); + if (damageWinPrivateIndex == -1) + return FALSE; + damageGeneration = serverGeneration; + } + if (pScreen->devPrivates[damageScrPrivateIndex].ptr) + return TRUE; + + if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec))) + return FALSE; + if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0)) + return FALSE; + if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0)) + return FALSE; + + pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec)); + if (!pScrPriv) + return FALSE; + +#ifdef COMPOSITE + /* This is a kludge to ensure wrapping order with the composite wrapper. + * If it's done from compinit.c, then DamageSetup may be called before the + * extension init phase, so that cw will be higher in the wrapping chain and + * rewrite drawables before damage gets to it, causing confusion. + */ + if (!noCompositeExtension) + miInitializeCompositeWrapper (pScreen); +#endif + + pScrPriv->internalLevel = 0; + pScrPriv->pScreenDamage = 0; + + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); + wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +#ifdef RENDER + if (ps) { + wrap (pScrPriv, ps, Glyphs, damageGlyphs); + wrap (pScrPriv, ps, Composite, damageComposite); + } +#endif + + pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv; + return TRUE; +} + +DamagePtr +DamageCreate (DamageReportFunc damageReport, + DamageDestroyFunc damageDestroy, + DamageReportLevel damageLevel, + Bool isInternal, + ScreenPtr pScreen, + void *closure) +{ + DamagePtr pDamage; + + pDamage = xalloc (sizeof (DamageRec)); + if (!pDamage) + return 0; + pDamage->pNext = 0; + pDamage->pNextWin = 0; + REGION_NULL(pScreen, &pDamage->damage); + + pDamage->damageLevel = damageLevel; + pDamage->isInternal = isInternal; + pDamage->closure = closure; + pDamage->isWindow = FALSE; + pDamage->pDrawable = 0; + + pDamage->damageReport = damageReport; + pDamage->damageDestroy = damageDestroy; + return pDamage; +} + +void +DamageRegister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef(pWindow); + +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) + if (pOld == pDamage) { + ErrorF ("Damage already on window list\n"); + abort (); + } +#endif + pDamage->pNextWin = *pPrev; + *pPrev = pDamage; + pDamage->isWindow = TRUE; + } + else + pDamage->isWindow = FALSE; + pDamage->pDrawable = pDrawable; + damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDrawInternal (ScreenPtr pScreen, Bool enable) +{ + damageScrPriv (pScreen); + + pScrPriv->internalLevel += enable ? 1 : -1; +} + +void +DamageUnregister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef (pWindow); +#if DAMAGE_VALIDATE_ENABLE + int found = 0; +#endif + + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNextWin; +#if DAMAGE_VALIDATE_ENABLE + found = 1; +#endif + break; + } + pPrev = &(*pPrev)->pNextWin; + } +#if DAMAGE_VALIDATE_ENABLE + if (!found) { + ErrorF ("Damage not on window list\n"); + abort (); + } +#endif + } + pDamage->pDrawable = 0; + damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDestroy (DamagePtr pDamage) +{ + if (pDamage->damageDestroy) + (*pDamage->damageDestroy) (pDamage, pDamage->closure); + REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage); + xfree (pDamage); +} + +Bool +DamageSubtract (DamagePtr pDamage, + const RegionPtr pRegion) +{ + RegionPtr pClip; + RegionRec pixmapClip; + DrawablePtr pDrawable = pDamage->pDrawable; + + REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion); + if (pDrawable) + { + if (pDrawable->type == DRAWABLE_WINDOW) + pClip = &((WindowPtr) pDrawable)->borderClip; + else + { + BoxRec box; + + box.x1 = pDrawable->x; + box.y1 = pDrawable->y; + box.x2 = pDrawable->x + pDrawable->width; + box.y2 = pDrawable->y + pDrawable->height; + REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1); + pClip = &pixmapClip; + } + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y); + REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip); + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y); + if (pDrawable->type != DRAWABLE_WINDOW) + REGION_UNINIT(pDrawable->pScreen, &pixmapClip); + } + return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage); +} + +void +DamageEmpty (DamagePtr pDamage) +{ + REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage); +} + +RegionPtr +DamageRegion (DamagePtr pDamage) +{ + return &pDamage->damage; +} + +void +DamageDamageRegion (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + damageDamageRegion (pDrawable, pRegion, FALSE, -1); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c new file mode 100644 index 000000000..845c6cfb9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c @@ -0,0 +1,4670 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.13 2005/09/13 01:33:19 daniels Exp $ */ +/* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.32 2003/11/10 18:21:45 tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef PANORAMIX_DEBUG +#include +int ProcInitialConnection(); +#endif + +#ifdef __sun +#define False 0 +#define True 1 +#endif + +#define GC XlibGC +#include +#undef GC + +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef XAPPGROUP +#include +#endif +#ifdef XKB +#define XKB_IN_SERVER +#include "inputstr.h" +#include +#endif + +#include "Atoms.h" +#include "Splash.h" +#include "Client.h" +#include "Clipboard.h" +#include "Reconnect.h" +#include "Millis.h" +#include "Font.h" +#include "Shadow.h" +#include "Handlers.h" +#include "Keyboard.h" + +const int nxagentMaxFontNames = 10000; + +char dispatchExceptionAtReset = DE_RESET; + +/* + * This allows the agent to exit if no + * client is connected within a timeout. + */ + +int nxagentClients = 0; + +void nxagentWaitDisplay(void); + +void nxagentListRemoteFonts(const char *, int); + +unsigned int nxagentWMtimeout = 0; +Bool nxagentWMPassed = 0; + +/* + * Timeouts based on screen saver time. + */ + +int nxagentAutoDisconnectTimeout = 0; + +#ifdef LBX +#include "../../lbx/lbxserve.h" +#endif + +#include "Xatom.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef WATCH + +/* + * Log begin and end of the important handlers. + */ + +#undef BLOCKS + +#ifdef WATCH +#include "unistd.h" +#endif + +#ifdef TEST +#include "Literals.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; + +Selection *CurrentSelections; +int NumCurrentSelections; +CallbackListPtr SelectionCallback = NULL; + +#ifdef VIEWPORT_FRAME + +extern WindowPtr nxagentViewportFrameLeft; +extern WindowPtr nxagentViewportFrameRight; +extern WindowPtr nxagentViewportFrameAbove; +extern WindowPtr nxagentViewportFrameBelow; + +#define IsViewportFrame(pWin) ((pWin) == nxagentViewportFrameLeft || \ + (pWin) == nxagentViewportFrameRight || \ + (pWin) == nxagentViewportFrameAbove || \ + (pWin) == nxagentViewportFrameBelow) + +#else + +#define IsViewportFrame(pWin) (0) + +#endif /* #ifdef VIEWPORT_FRAME */ + +extern int nxagentMaxAllowedResets; + +extern int nxagentFindClientResource(int, RESTYPE, pointer); + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +static void KillAllClients(void); + +static void DeleteClientFromAnySelections(ClientPtr client); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; + +/* dispatchException & isItTimeToYield must be declared volatile since they + * are modified by signal handlers - otherwise optimizer may assume it doesn't + * need to actually check value in memory when used and may miss changes from + * signal handlers. + */ +volatile char dispatchException = 0; +volatile char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; + +#ifdef NXAGENT_CLIPBOARD + { + Selection *newsels; + newsels = (Selection *)xalloc(2 * sizeof(Selection)); + if (!newsels) + return; + NumCurrentSelections += 2; + CurrentSelections = newsels; + + CurrentSelections[0].selection = XA_PRIMARY; + CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[0].window = WindowTable[0]->drawable.id; + CurrentSelections[0].pWin = NULL; + CurrentSelections[0].client = NullClient; + + CurrentSelections[1].selection = MakeAtom("CLIPBOARD", 9, 1); + CurrentSelections[1].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[1].window = WindowTable[0]->drawable.id; + CurrentSelections[1].pWin = NULL; + CurrentSelections[1].client = NullClient; + } +#endif + +} + +void +FlushClientCaches(XID id) +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; ilastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} +#ifdef SMART_SCHEDULE + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +Bool SmartScheduleDisable = FALSE; +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +ClientPtr SmartLastClient; +int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; +int SmartScheduleClient(int *clientReady, int nready); + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); +void InitProcVectors(void); + +int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} +#endif + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; +#ifdef SMART_SCHEDULE + long start_tick; +#endif + + unsigned long currentDispatch = 0; + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + /* + * The agent initialization was successfully + * completed. We can now handle our clients. + */ + + if (serverGeneration > nxagentMaxAllowedResets) + { + fprintf(stderr, "Session: Session started at '%s'.\n", GetTimeAsString()); + + nxagentSessionState = SESSION_UP; + } + + #ifdef XKB + + nxagentInitXkbWrapper(); + + nxagentTuneXkbWrapper(); + + #endif + + #ifdef NXAGENT_ONSTART + + /* + * Set NX_WM property (used by NX client to identify + * the agent's window) three seconds since the first + * client connects. + */ + + nxagentWMtimeout = GetTimeInMillis() + 3000; + + #endif + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + #ifdef WATCH + + fprintf(stderr, "Dispatch: Watchpoint 12.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#3 1 352 bits (0 KB) -> 236 bits (0 KB) -> 352/1 -> 236/1 = 1.492:1 +#14 1 256 bits (0 KB) -> 101 bits (0 KB) -> 256/1 -> 101/1 = 2.535:1 +#16 1 256 bits (0 KB) -> 26 bits (0 KB) -> 256/1 -> 26/1 = 9.846:1 +#20 2 2 12256 bits (1 KB) -> 56 bits (0 KB) -> 6128/1 -> 28/1 = 218.857:1 +#43 1 256 bits (0 KB) -> 45 bits (0 KB) -> 256/1 -> 45/1 = 5.689:1 +#47 2 2 42304 bits (5 KB) -> 49 bits (0 KB) -> 21152/1 -> 24/1 = 863.347:1 +#98 1 256 bits (0 KB) -> 34 bits (0 KB) -> 256/1 -> 34/1 = 7.529:1 +*/ + + sleep(30); + + #endif + + #ifdef TEST + fprintf(stderr, "Dispatch: Value of dispatchException is [%x].\n", + dispatchException); + + fprintf(stderr, "Dispatch: Value of dispatchExceptionAtReset is [%x].\n", + dispatchExceptionAtReset); + #endif + + if (!(dispatchException & DE_TERMINATE)) + dispatchException = 0; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + /* + * Ensure we remove the splash after the timeout. + * Initializing clientReady[0] to -1 will tell + * WaitForSomething() to yield control after the + * timeout set in clientReady[1]. + */ + + clientReady[0] = 0; + + if (nxagentSplashWindow != None || (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0)) + { + #ifdef TEST + fprintf(stderr, "******Dispatch: Requesting a timeout of [%d] Ms.\n", + NXAGENT_WAKEUP); + #endif + + clientReady[0] = -1; + clientReady[1] = NXAGENT_WAKEUP; + } + + #ifdef BLOCKS + fprintf(stderr, "[End dispatch]\n"); + #endif + + nready = WaitForSomething(clientReady); + + #ifdef BLOCKS + fprintf(stderr, "[Begin dispatch]\n"); + #endif + + #ifdef TEST + fprintf(stderr, "******Dispatch: Running with [%d] clients ready.\n", + nready); + #endif + + #ifdef NXAGENT_ONSTART + + currentDispatch = GetTimeInMillis(); + + /* + * If the timeout is expired set the + * selection informing the NX client + * that the agent is ready. + */ + + if (!nxagentWMPassed && (nxagentWMtimeout < currentDispatch)) + { + nxagentRemoveSplashWindow(NULL); + } + + nxagentClients = nClients; + + #endif + +#ifdef SMART_SCHEDULE + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } +#endif + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; +#ifdef SMART_SCHEDULE + start_tick = SmartScheduleTime; +#endif + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } +#endif + /* now, finally, deal with client requests */ + + #ifdef TEST + fprintf(stderr, "******Dispatch: Reading request from client [%d].\n", + client->index); + #endif + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } +#ifdef NXAGENT_SERVER + + #ifdef TEST + + else + { + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Read [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d].\n", MAJOROP, *((char *) client->requestBuffer + 1), + client->req_len << 2, client->index); + } + else + { + fprintf(stderr, "******Dispatch: Read [%s] request OPCODE#%d size [%d] client [%d].\n", + nxagentRequestLiteral[MAJOROP], MAJOROP, client->req_len << 2, + client->index); + } + } + + #endif +#endif + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (maxBigRequestSize << 2)) + result = BadLength; + else +#ifdef NXAGENT_SERVER + { + result = (* client->requestVector[MAJOROP])(client); + + #ifdef TEST + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Handled [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d] result [%d].\n", MAJOROP, + *((char *) client->requestBuffer + 1), client->req_len << 2, + client->index, result); + } + else + { + fprintf(stderr, "******Dispatch: Handled [%s] request OPCODE#%d size [%d] client [%d] " + "result [%d].\n", nxagentRequestLiteral[MAJOROP], MAJOROP, + client->req_len << 2, client->index, result); + } + + #endif + + /* + * Can set isItTimeToYield to force + * the dispatcher to pay attention + * to another client. + */ + + nxagentDispatchHandler(client, client->req_len << 2, 0); + } +#else + result = (* client->requestVector[MAJOROP])(client); +#endif + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } +#ifdef DAMAGEEXT + FlushIfCriticalOutputPending (); +#endif + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } +#if defined(DDXBEFORERESET) + ddxBeforeReset (); +#endif + if ((dispatchException & DE_RESET) && + (serverGeneration > nxagentMaxAllowedResets)) + { + dispatchException &= ~DE_RESET; + dispatchException |= DE_TERMINATE; + + fprintf(stderr, "Info: Reached threshold of maximum allowed resets.\n"); + } + + nxagentResetAtomMap(); + + if (serverGeneration > nxagentMaxAllowedResets) + { + /* + * The session is terminating. Force an I/O + * error on the display and wait until the + * NX transport is gone. + */ + + fprintf(stderr, "Session: Terminating session at '%s'.\n", GetTimeAsString()); + + nxagentWaitDisplay(); + + fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString()); + } + + if (nxagentOption(Shadow) == 1) + { + NXShadowDestroy(); + } + + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +int +ProcBadRequest(ClientPtr client) +{ + return (BadRequest); +} + +int +ProcCreateWindow(ClientPtr client) +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(register ClientPtr client) +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + + if (!nxagentWMPassed) + { + nxagentRemoveSplashWindow(pWin); + } + + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + + return(client->noClientException); +} + +int +ProcUnmapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(register ClientPtr client, xGetGeometryReply *rep) +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(register ClientPtr client) +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(register ClientPtr client) +{ + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + numChildren++; + } + } + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + childIDs[curChild++] = pChild->drawable.id; + } + } + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(register ClientPtr client) +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(register ClientPtr client) +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(register ClientPtr client) +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind= SelectionSetOwner; + CallCallbacks(&SelectionCallback, &info); + } + +#ifdef NXAGENT_CLIPBOARD + if ((CurrentSelections[i].pWin != NULL) && + (nxagentOption(Clipboard) != ClipboardNone) && + ((CurrentSelections[i].selection == XA_PRIMARY) || + (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0)))) + { + nxagentSetSelectionOwner(&CurrentSelections[i]); + } +#endif + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(register ClientPtr client) +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(register ClientPtr client) +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + +#ifdef NXAGENT_CLIPBOARD + if (((stuff->selection == XA_PRIMARY) || + (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) && + nxagentOption(Clipboard) != ClipboardNone) + { + int i = 0; + + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + + if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None)) + { + if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor, + stuff->property, stuff->target, stuff->time)) + { + return (client->noClientException); + } + } + } +#endif + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient) +#ifdef XCSECURITY + && (!client->CheckAccess || + (* client->CheckAccess)(client, CurrentSelections[i].window, + RT_WINDOW, SecurityReadAccess, + CurrentSelections[i].pWin)) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +UngrabServer(ClientPtr client) +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(register ClientPtr client) +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) + + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(register ClientPtr client) +{ + int err; + char fontReq[256]; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + + memcpy(fontReq,(char *)&stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + fontReq[stuff->nbytes]=0; + if (strchr(fontReq,'*') || strchr(fontReq,'?')) + { + extern int nxOpenFont(ClientPtr, XID, Mask, unsigned, char*); +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ProcOpenFont try to find a common font with font pattern=%s\n",fontReq); +#endif + nxagentListRemoteFonts(fontReq, nxagentMaxFontNames); + err = nxOpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + } + else + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(register ClientPtr client) +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if (pFont != (FontPtr)NULL) + { + #ifdef NXAGENT_SERVER + + /* + * When a client closes a font the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this font looping through the + * resources. + */ + + if (pFont -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_FONT, pFont) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcCloseFont: Switching resource for font at [%p].\n", + (void *) pFont); + #endif + + nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index); + + AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont); + + } + #ifdef TEST + else + { + fprintf(stderr, "ProcCloseFont: Found duplicated font at [%p], " + "resource switching skipped.\n", (void *) pFont); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(register ClientPtr client) +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + + pFont = NULL; + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + +/* test +{ + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if (props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return (BadFont); + + name = (char *)NameForAtom(value_atom); + fprintf(stderr, "QueryFont: font name [%s]\n",name); +} + end test */ + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = NULL; + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(register ClientPtr client) +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(register ClientPtr client) +{ + char tmp[256]; + + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames : stuff->maxNames); + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(register ClientPtr client) +{ + char tmp[256]; + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont with info request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames :stuff->maxNames); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/** + * + * \param value must conform to DeleteType + */ +int +dixDestroyPixmap(pointer value, XID pid) +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->width > 32767 || stuff->height > 32767) + { + /* It is allowed to try and allocate a pixmap which is larger than + * 32767 in either dimension. However, all of the framebuffer code + * is buggy and does not reliably draw to such big pixmaps, basically + * because the Region data structure operates with signed shorts + * for the rectangles in it. + * + * Furthermore, several places in the X server computes the + * size in bytes of the pixmap and tries to store it in an + * integer. This integer can overflow and cause the allocated size + * to be much smaller. + * + * So, such big pixmaps are rejected here with a BadAlloc + */ + return BadAlloc; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + #ifdef NXAGENT_SERVER + + /* + * When a client releases a pixmap the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this pixmap looping through the + * resources. + */ + + if (pMap -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_PIXMAP, pMap) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcFreePixmap: Switching resource for pixmap at [%p].\n", + (void *) pMap); + #endif + + nxagentPixmapPriv(pMap) -> mid = FakeClientID(serverClient -> index); + + AddResource(nxagentPixmapPriv(pMap) -> mid, RT_NX_PIXMAP, pMap); + } + #ifdef TEST + else + { + fprintf(stderr, "ProcFreePixmap: Found duplicated pixmap at [%p], " + "resource switching skipped.\n", (void *) pMap); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(register ClientPtr client) +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(register ClientPtr client) +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(register ClientPtr client) +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(register ClientPtr client) +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(register ClientPtr client) +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(register ClientPtr client) +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(register ClientPtr client) +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(register ClientPtr client) +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(register ClientPtr client) +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + { + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyLine(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + { + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolySegment(register ClientPtr client) +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + { + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyRectangle (register ClientPtr client) +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + { + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcFillPoly(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + { + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyFillRectangle(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + + if (things) + { + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyFillArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(register ClientPtr client) +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return (client->noClientException); +} + + +int +DoGetImage(register ClientPtr client, int format, Drawable drawable, + int x, int y, int width, int height, + Mask planemask, xGetImageReply **im_return) +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; +#ifdef XCSECURITY + RegionPtr pVisibleRegion = NULL; +#endif + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XCSECURITY + if (client->trustLevel != XSecurityClientTrusted && + pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } +#ifdef XCSECURITY + if (pVisibleRegion) + REGION_DESTROY(pDraw->pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(register ClientPtr client) +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(register ClientPtr client) +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(register ClientPtr client) +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadValue); +} + +int +ProcFreeColormap(register ClientPtr client) +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(register ClientPtr client) +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(register ClientPtr client) +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor (register ClientPtr client) +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pmap, (xReq *) stuff)) + return Success; +#endif + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocNamedColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorCells request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorPlanes request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor (register ClientPtr client) +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + { + #ifdef TEST + fprintf(stderr, "ProcCreateCursor: Created cursor at [%p].\n", (void *) pCursor); + #endif + + return (client->noClientException); + } + + return BadAlloc; +} + +int +ProcCreateGlyphCursor (register ClientPtr client) +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor (register ClientPtr client) +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (register ClientPtr client) +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (register ClientPtr client) +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to change our values. + */ + + #ifdef TEST + fprintf(stderr, "ProcSetScreenSaver: Called with timeout [%d] interval [%d] Blanking [%d] Exposure [%d].\n", + stuff -> timeout, stuff -> interval, blankingOption, exposureOption); + #endif + + if (nxagentOption(Timeout) == 0) + { + if (blankingOption == DefaultBlanking) + { + ScreenSaverBlanking = defaultScreenSaverBlanking; + } + else + { + ScreenSaverBlanking = blankingOption; + } + + if (exposureOption == DefaultExposures) + { + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + } + else + { + ScreenSaverAllowExposures = exposureOption; + } + + if (stuff->timeout >= 0) + { + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + } + else + { + ScreenSaverTime = defaultScreenSaverTime; + } + + if (stuff->interval >= 0) + { + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + } + else + { + ScreenSaverInterval = defaultScreenSaverInterval; + } + } + #ifdef TEST + + else + { + fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n", + nxagentOption(Timeout)); + } + + #endif + + SetScreenSaverTimer(); + return (client->noClientException); +} + +int +ProcGetScreenSaver(register ClientPtr client) +{ + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(register ClientPtr client) +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(register ClientPtr client) +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XCSECURITY + /* untrusted clients can't list hosts */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to list hosts\n", client->index); + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(register ClientPtr client) +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(register ClientPtr client) +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(register ClientPtr client) +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(register ClientPtr client) +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(register ClientPtr client) +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(register ClientPtr client) +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to force the screen + * saver handler execution. + */ + + if (nxagentOption(Timeout) == 0) + { + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + } + + #ifdef TEST + + else + { + fprintf(stderr, "ProcForceScreenSaver: Ignoring the client request with mode [%d].\n", + stuff -> mode); + } + + #endif + + return client->noClientException; +} + +int ProcNoOperation(register ClientPtr client) +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors(void) +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = ReplyNotSwappd; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +void +CloseDownClient(register ClientPtr client) +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + /* + * There must be a better way to hook a + * call-back function to be called any + * time a client is going to be closed. + */ + + nxagentClearClipboard(client, NULL); + + /* + * Need to reset the karma counter and + * get rid of the pending sync replies. + */ + + nxagentWakeupByReset(client); + + /* + * Check if the client + * is a shadow nxagent. + */ + + nxagentCheckIfShadowAgent(client); + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); +#ifdef LBX + ProcessQTagZombies(); +#endif + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; +#ifdef SMART_SCHEDULE + SmartLastClient = NullClient; +#endif + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; icloseDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; icloseDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +void InitClient(ClientPtr client, int i, pointer ospriv) +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; + client->noClientException = Success; +#ifdef LOG_DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef LBX + client->readRequest = StandardReadRequestFromClient; +#endif +#ifdef XCSECURITY + client->trustLevel = XSecurityClientTrusted; + client->CheckAccess = NULL; + client->authId = 0; +#endif +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +#ifdef SMART_SCHEDULE + client->smart_priority = 0; + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; +#endif +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +int +InitClientPrivates(ClientPtr client) +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + + /* + * Initialize the private members. + */ + + nxagentInitClientPrivates(client); + + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr NextAvailableClient(pointer ospriv) +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(register ClientPtr client) +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +#ifdef LBX +void +IncrementClientCount() +{ + nClients++; +} +#endif + +int +SendConnSetup(register ClientPtr client, char *reason) +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; icurrentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(register ClientPtr client) +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +void +SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, + XID resId, int errorCode) +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(WindowPtr pWin) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(ClientPtr client) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(ClientPtr client) +{ + client->noClientException = -1; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.NX.original new file mode 100644 index 000000000..845c6cfb9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.NX.original @@ -0,0 +1,4670 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.13 2005/09/13 01:33:19 daniels Exp $ */ +/* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.32 2003/11/10 18:21:45 tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef PANORAMIX_DEBUG +#include +int ProcInitialConnection(); +#endif + +#ifdef __sun +#define False 0 +#define True 1 +#endif + +#define GC XlibGC +#include +#undef GC + +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef XAPPGROUP +#include +#endif +#ifdef XKB +#define XKB_IN_SERVER +#include "inputstr.h" +#include +#endif + +#include "Atoms.h" +#include "Splash.h" +#include "Client.h" +#include "Clipboard.h" +#include "Reconnect.h" +#include "Millis.h" +#include "Font.h" +#include "Shadow.h" +#include "Handlers.h" +#include "Keyboard.h" + +const int nxagentMaxFontNames = 10000; + +char dispatchExceptionAtReset = DE_RESET; + +/* + * This allows the agent to exit if no + * client is connected within a timeout. + */ + +int nxagentClients = 0; + +void nxagentWaitDisplay(void); + +void nxagentListRemoteFonts(const char *, int); + +unsigned int nxagentWMtimeout = 0; +Bool nxagentWMPassed = 0; + +/* + * Timeouts based on screen saver time. + */ + +int nxagentAutoDisconnectTimeout = 0; + +#ifdef LBX +#include "../../lbx/lbxserve.h" +#endif + +#include "Xatom.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef WATCH + +/* + * Log begin and end of the important handlers. + */ + +#undef BLOCKS + +#ifdef WATCH +#include "unistd.h" +#endif + +#ifdef TEST +#include "Literals.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; + +Selection *CurrentSelections; +int NumCurrentSelections; +CallbackListPtr SelectionCallback = NULL; + +#ifdef VIEWPORT_FRAME + +extern WindowPtr nxagentViewportFrameLeft; +extern WindowPtr nxagentViewportFrameRight; +extern WindowPtr nxagentViewportFrameAbove; +extern WindowPtr nxagentViewportFrameBelow; + +#define IsViewportFrame(pWin) ((pWin) == nxagentViewportFrameLeft || \ + (pWin) == nxagentViewportFrameRight || \ + (pWin) == nxagentViewportFrameAbove || \ + (pWin) == nxagentViewportFrameBelow) + +#else + +#define IsViewportFrame(pWin) (0) + +#endif /* #ifdef VIEWPORT_FRAME */ + +extern int nxagentMaxAllowedResets; + +extern int nxagentFindClientResource(int, RESTYPE, pointer); + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +static void KillAllClients(void); + +static void DeleteClientFromAnySelections(ClientPtr client); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; + +/* dispatchException & isItTimeToYield must be declared volatile since they + * are modified by signal handlers - otherwise optimizer may assume it doesn't + * need to actually check value in memory when used and may miss changes from + * signal handlers. + */ +volatile char dispatchException = 0; +volatile char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; + +#ifdef NXAGENT_CLIPBOARD + { + Selection *newsels; + newsels = (Selection *)xalloc(2 * sizeof(Selection)); + if (!newsels) + return; + NumCurrentSelections += 2; + CurrentSelections = newsels; + + CurrentSelections[0].selection = XA_PRIMARY; + CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[0].window = WindowTable[0]->drawable.id; + CurrentSelections[0].pWin = NULL; + CurrentSelections[0].client = NullClient; + + CurrentSelections[1].selection = MakeAtom("CLIPBOARD", 9, 1); + CurrentSelections[1].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[1].window = WindowTable[0]->drawable.id; + CurrentSelections[1].pWin = NULL; + CurrentSelections[1].client = NullClient; + } +#endif + +} + +void +FlushClientCaches(XID id) +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; ilastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} +#ifdef SMART_SCHEDULE + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +Bool SmartScheduleDisable = FALSE; +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +ClientPtr SmartLastClient; +int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; +int SmartScheduleClient(int *clientReady, int nready); + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); +void InitProcVectors(void); + +int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} +#endif + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; +#ifdef SMART_SCHEDULE + long start_tick; +#endif + + unsigned long currentDispatch = 0; + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + /* + * The agent initialization was successfully + * completed. We can now handle our clients. + */ + + if (serverGeneration > nxagentMaxAllowedResets) + { + fprintf(stderr, "Session: Session started at '%s'.\n", GetTimeAsString()); + + nxagentSessionState = SESSION_UP; + } + + #ifdef XKB + + nxagentInitXkbWrapper(); + + nxagentTuneXkbWrapper(); + + #endif + + #ifdef NXAGENT_ONSTART + + /* + * Set NX_WM property (used by NX client to identify + * the agent's window) three seconds since the first + * client connects. + */ + + nxagentWMtimeout = GetTimeInMillis() + 3000; + + #endif + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + #ifdef WATCH + + fprintf(stderr, "Dispatch: Watchpoint 12.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#3 1 352 bits (0 KB) -> 236 bits (0 KB) -> 352/1 -> 236/1 = 1.492:1 +#14 1 256 bits (0 KB) -> 101 bits (0 KB) -> 256/1 -> 101/1 = 2.535:1 +#16 1 256 bits (0 KB) -> 26 bits (0 KB) -> 256/1 -> 26/1 = 9.846:1 +#20 2 2 12256 bits (1 KB) -> 56 bits (0 KB) -> 6128/1 -> 28/1 = 218.857:1 +#43 1 256 bits (0 KB) -> 45 bits (0 KB) -> 256/1 -> 45/1 = 5.689:1 +#47 2 2 42304 bits (5 KB) -> 49 bits (0 KB) -> 21152/1 -> 24/1 = 863.347:1 +#98 1 256 bits (0 KB) -> 34 bits (0 KB) -> 256/1 -> 34/1 = 7.529:1 +*/ + + sleep(30); + + #endif + + #ifdef TEST + fprintf(stderr, "Dispatch: Value of dispatchException is [%x].\n", + dispatchException); + + fprintf(stderr, "Dispatch: Value of dispatchExceptionAtReset is [%x].\n", + dispatchExceptionAtReset); + #endif + + if (!(dispatchException & DE_TERMINATE)) + dispatchException = 0; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + /* + * Ensure we remove the splash after the timeout. + * Initializing clientReady[0] to -1 will tell + * WaitForSomething() to yield control after the + * timeout set in clientReady[1]. + */ + + clientReady[0] = 0; + + if (nxagentSplashWindow != None || (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0)) + { + #ifdef TEST + fprintf(stderr, "******Dispatch: Requesting a timeout of [%d] Ms.\n", + NXAGENT_WAKEUP); + #endif + + clientReady[0] = -1; + clientReady[1] = NXAGENT_WAKEUP; + } + + #ifdef BLOCKS + fprintf(stderr, "[End dispatch]\n"); + #endif + + nready = WaitForSomething(clientReady); + + #ifdef BLOCKS + fprintf(stderr, "[Begin dispatch]\n"); + #endif + + #ifdef TEST + fprintf(stderr, "******Dispatch: Running with [%d] clients ready.\n", + nready); + #endif + + #ifdef NXAGENT_ONSTART + + currentDispatch = GetTimeInMillis(); + + /* + * If the timeout is expired set the + * selection informing the NX client + * that the agent is ready. + */ + + if (!nxagentWMPassed && (nxagentWMtimeout < currentDispatch)) + { + nxagentRemoveSplashWindow(NULL); + } + + nxagentClients = nClients; + + #endif + +#ifdef SMART_SCHEDULE + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } +#endif + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; +#ifdef SMART_SCHEDULE + start_tick = SmartScheduleTime; +#endif + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } +#endif + /* now, finally, deal with client requests */ + + #ifdef TEST + fprintf(stderr, "******Dispatch: Reading request from client [%d].\n", + client->index); + #endif + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } +#ifdef NXAGENT_SERVER + + #ifdef TEST + + else + { + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Read [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d].\n", MAJOROP, *((char *) client->requestBuffer + 1), + client->req_len << 2, client->index); + } + else + { + fprintf(stderr, "******Dispatch: Read [%s] request OPCODE#%d size [%d] client [%d].\n", + nxagentRequestLiteral[MAJOROP], MAJOROP, client->req_len << 2, + client->index); + } + } + + #endif +#endif + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (maxBigRequestSize << 2)) + result = BadLength; + else +#ifdef NXAGENT_SERVER + { + result = (* client->requestVector[MAJOROP])(client); + + #ifdef TEST + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Handled [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d] result [%d].\n", MAJOROP, + *((char *) client->requestBuffer + 1), client->req_len << 2, + client->index, result); + } + else + { + fprintf(stderr, "******Dispatch: Handled [%s] request OPCODE#%d size [%d] client [%d] " + "result [%d].\n", nxagentRequestLiteral[MAJOROP], MAJOROP, + client->req_len << 2, client->index, result); + } + + #endif + + /* + * Can set isItTimeToYield to force + * the dispatcher to pay attention + * to another client. + */ + + nxagentDispatchHandler(client, client->req_len << 2, 0); + } +#else + result = (* client->requestVector[MAJOROP])(client); +#endif + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } +#ifdef DAMAGEEXT + FlushIfCriticalOutputPending (); +#endif + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } +#if defined(DDXBEFORERESET) + ddxBeforeReset (); +#endif + if ((dispatchException & DE_RESET) && + (serverGeneration > nxagentMaxAllowedResets)) + { + dispatchException &= ~DE_RESET; + dispatchException |= DE_TERMINATE; + + fprintf(stderr, "Info: Reached threshold of maximum allowed resets.\n"); + } + + nxagentResetAtomMap(); + + if (serverGeneration > nxagentMaxAllowedResets) + { + /* + * The session is terminating. Force an I/O + * error on the display and wait until the + * NX transport is gone. + */ + + fprintf(stderr, "Session: Terminating session at '%s'.\n", GetTimeAsString()); + + nxagentWaitDisplay(); + + fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString()); + } + + if (nxagentOption(Shadow) == 1) + { + NXShadowDestroy(); + } + + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +int +ProcBadRequest(ClientPtr client) +{ + return (BadRequest); +} + +int +ProcCreateWindow(ClientPtr client) +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(register ClientPtr client) +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + + if (!nxagentWMPassed) + { + nxagentRemoveSplashWindow(pWin); + } + + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + + return(client->noClientException); +} + +int +ProcUnmapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(register ClientPtr client, xGetGeometryReply *rep) +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(register ClientPtr client) +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(register ClientPtr client) +{ + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + numChildren++; + } + } + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { + childIDs[curChild++] = pChild->drawable.id; + } + } + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(register ClientPtr client) +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(register ClientPtr client) +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(register ClientPtr client) +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind= SelectionSetOwner; + CallCallbacks(&SelectionCallback, &info); + } + +#ifdef NXAGENT_CLIPBOARD + if ((CurrentSelections[i].pWin != NULL) && + (nxagentOption(Clipboard) != ClipboardNone) && + ((CurrentSelections[i].selection == XA_PRIMARY) || + (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0)))) + { + nxagentSetSelectionOwner(&CurrentSelections[i]); + } +#endif + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(register ClientPtr client) +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(register ClientPtr client) +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + +#ifdef NXAGENT_CLIPBOARD + if (((stuff->selection == XA_PRIMARY) || + (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) && + nxagentOption(Clipboard) != ClipboardNone) + { + int i = 0; + + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + + if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None)) + { + if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor, + stuff->property, stuff->target, stuff->time)) + { + return (client->noClientException); + } + } + } +#endif + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient) +#ifdef XCSECURITY + && (!client->CheckAccess || + (* client->CheckAccess)(client, CurrentSelections[i].window, + RT_WINDOW, SecurityReadAccess, + CurrentSelections[i].pWin)) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +UngrabServer(ClientPtr client) +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(register ClientPtr client) +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) + + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(register ClientPtr client) +{ + int err; + char fontReq[256]; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + + memcpy(fontReq,(char *)&stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + fontReq[stuff->nbytes]=0; + if (strchr(fontReq,'*') || strchr(fontReq,'?')) + { + extern int nxOpenFont(ClientPtr, XID, Mask, unsigned, char*); +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ProcOpenFont try to find a common font with font pattern=%s\n",fontReq); +#endif + nxagentListRemoteFonts(fontReq, nxagentMaxFontNames); + err = nxOpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + } + else + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(register ClientPtr client) +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if (pFont != (FontPtr)NULL) + { + #ifdef NXAGENT_SERVER + + /* + * When a client closes a font the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this font looping through the + * resources. + */ + + if (pFont -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_FONT, pFont) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcCloseFont: Switching resource for font at [%p].\n", + (void *) pFont); + #endif + + nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index); + + AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont); + + } + #ifdef TEST + else + { + fprintf(stderr, "ProcCloseFont: Found duplicated font at [%p], " + "resource switching skipped.\n", (void *) pFont); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(register ClientPtr client) +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + + pFont = NULL; + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + +/* test +{ + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if (props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return (BadFont); + + name = (char *)NameForAtom(value_atom); + fprintf(stderr, "QueryFont: font name [%s]\n",name); +} + end test */ + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = NULL; + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(register ClientPtr client) +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(register ClientPtr client) +{ + char tmp[256]; + + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames : stuff->maxNames); + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(register ClientPtr client) +{ + char tmp[256]; + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont with info request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames :stuff->maxNames); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/** + * + * \param value must conform to DeleteType + */ +int +dixDestroyPixmap(pointer value, XID pid) +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->width > 32767 || stuff->height > 32767) + { + /* It is allowed to try and allocate a pixmap which is larger than + * 32767 in either dimension. However, all of the framebuffer code + * is buggy and does not reliably draw to such big pixmaps, basically + * because the Region data structure operates with signed shorts + * for the rectangles in it. + * + * Furthermore, several places in the X server computes the + * size in bytes of the pixmap and tries to store it in an + * integer. This integer can overflow and cause the allocated size + * to be much smaller. + * + * So, such big pixmaps are rejected here with a BadAlloc + */ + return BadAlloc; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + #ifdef NXAGENT_SERVER + + /* + * When a client releases a pixmap the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this pixmap looping through the + * resources. + */ + + if (pMap -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_PIXMAP, pMap) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcFreePixmap: Switching resource for pixmap at [%p].\n", + (void *) pMap); + #endif + + nxagentPixmapPriv(pMap) -> mid = FakeClientID(serverClient -> index); + + AddResource(nxagentPixmapPriv(pMap) -> mid, RT_NX_PIXMAP, pMap); + } + #ifdef TEST + else + { + fprintf(stderr, "ProcFreePixmap: Found duplicated pixmap at [%p], " + "resource switching skipped.\n", (void *) pMap); + } + #endif + } + + #endif + + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(register ClientPtr client) +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(register ClientPtr client) +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(register ClientPtr client) +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(register ClientPtr client) +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(register ClientPtr client) +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(register ClientPtr client) +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(register ClientPtr client) +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(register ClientPtr client) +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(register ClientPtr client) +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + { + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyLine(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + { + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolySegment(register ClientPtr client) +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + { + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyRectangle (register ClientPtr client) +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + { + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcFillPoly(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + { + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + } + return(client->noClientException); +} + +int +ProcPolyFillRectangle(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + + if (things) + { + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + } + return (client->noClientException); +} + +int +ProcPolyFillArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + { + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + } + return (client->noClientException); +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(register ClientPtr client) +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return (client->noClientException); +} + + +int +DoGetImage(register ClientPtr client, int format, Drawable drawable, + int x, int y, int width, int height, + Mask planemask, xGetImageReply **im_return) +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; +#ifdef XCSECURITY + RegionPtr pVisibleRegion = NULL; +#endif + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XCSECURITY + if (client->trustLevel != XSecurityClientTrusted && + pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } +#ifdef XCSECURITY + if (pVisibleRegion) + REGION_DESTROY(pDraw->pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(register ClientPtr client) +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(register ClientPtr client) +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(register ClientPtr client) +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadValue); +} + +int +ProcFreeColormap(register ClientPtr client) +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(register ClientPtr client) +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(register ClientPtr client) +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor (register ClientPtr client) +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pmap, (xReq *) stuff)) + return Success; +#endif + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocNamedColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorCells request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorPlanes request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor (register ClientPtr client) +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + { + #ifdef TEST + fprintf(stderr, "ProcCreateCursor: Created cursor at [%p].\n", (void *) pCursor); + #endif + + return (client->noClientException); + } + + return BadAlloc; +} + +int +ProcCreateGlyphCursor (register ClientPtr client) +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor (register ClientPtr client) +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (register ClientPtr client) +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (register ClientPtr client) +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to change our values. + */ + + #ifdef TEST + fprintf(stderr, "ProcSetScreenSaver: Called with timeout [%d] interval [%d] Blanking [%d] Exposure [%d].\n", + stuff -> timeout, stuff -> interval, blankingOption, exposureOption); + #endif + + if (nxagentOption(Timeout) == 0) + { + if (blankingOption == DefaultBlanking) + { + ScreenSaverBlanking = defaultScreenSaverBlanking; + } + else + { + ScreenSaverBlanking = blankingOption; + } + + if (exposureOption == DefaultExposures) + { + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + } + else + { + ScreenSaverAllowExposures = exposureOption; + } + + if (stuff->timeout >= 0) + { + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + } + else + { + ScreenSaverTime = defaultScreenSaverTime; + } + + if (stuff->interval >= 0) + { + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + } + else + { + ScreenSaverInterval = defaultScreenSaverInterval; + } + } + #ifdef TEST + + else + { + fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n", + nxagentOption(Timeout)); + } + + #endif + + SetScreenSaverTimer(); + return (client->noClientException); +} + +int +ProcGetScreenSaver(register ClientPtr client) +{ + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(register ClientPtr client) +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(register ClientPtr client) +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XCSECURITY + /* untrusted clients can't list hosts */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to list hosts\n", client->index); + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(register ClientPtr client) +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(register ClientPtr client) +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(register ClientPtr client) +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(register ClientPtr client) +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(register ClientPtr client) +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(register ClientPtr client) +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to force the screen + * saver handler execution. + */ + + if (nxagentOption(Timeout) == 0) + { + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + } + + #ifdef TEST + + else + { + fprintf(stderr, "ProcForceScreenSaver: Ignoring the client request with mode [%d].\n", + stuff -> mode); + } + + #endif + + return client->noClientException; +} + +int ProcNoOperation(register ClientPtr client) +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors(void) +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = ReplyNotSwappd; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +void +CloseDownClient(register ClientPtr client) +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + /* + * There must be a better way to hook a + * call-back function to be called any + * time a client is going to be closed. + */ + + nxagentClearClipboard(client, NULL); + + /* + * Need to reset the karma counter and + * get rid of the pending sync replies. + */ + + nxagentWakeupByReset(client); + + /* + * Check if the client + * is a shadow nxagent. + */ + + nxagentCheckIfShadowAgent(client); + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); +#ifdef LBX + ProcessQTagZombies(); +#endif + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; +#ifdef SMART_SCHEDULE + SmartLastClient = NullClient; +#endif + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; icloseDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; icloseDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +void InitClient(ClientPtr client, int i, pointer ospriv) +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; + client->noClientException = Success; +#ifdef LOG_DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef LBX + client->readRequest = StandardReadRequestFromClient; +#endif +#ifdef XCSECURITY + client->trustLevel = XSecurityClientTrusted; + client->CheckAccess = NULL; + client->authId = 0; +#endif +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +#ifdef SMART_SCHEDULE + client->smart_priority = 0; + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; +#endif +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +int +InitClientPrivates(ClientPtr client) +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + + /* + * Initialize the private members. + */ + + nxagentInitClientPrivates(client); + + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr NextAvailableClient(pointer ospriv) +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(register ClientPtr client) +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +#ifdef LBX +void +IncrementClientCount() +{ + nClients++; +} +#endif + +int +SendConnSetup(register ClientPtr client, char *reason) +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; icurrentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(register ClientPtr client) +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +void +SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, + XID resId, int errorCode) +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(WindowPtr pWin) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(ClientPtr client) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(ClientPtr client) +{ + client->noClientException = -1; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original new file mode 100644 index 000000000..6941456de --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original @@ -0,0 +1,4035 @@ +/* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.13 2005/09/13 01:33:19 daniels Exp $ */ +/* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/dispatch.c,v 3.32 2003/11/10 18:21:45 tsi Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef PANORAMIX_DEBUG +#include +int ProcInitialConnection(); +#endif + +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef XAPPGROUP +#include +#endif +#ifdef XKB +#define XKB_IN_SERVER +#include "inputstr.h" +#include +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; + +Selection *CurrentSelections; +int NumCurrentSelections; +CallbackListPtr SelectionCallback = NULL; + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +extern int connBlockScreenStart; + +static void KillAllClients(void); + +static void DeleteClientFromAnySelections(ClientPtr client); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; + +/* dispatchException & isItTimeToYield must be declared volatile since they + * are modified by signal handlers - otherwise optimizer may assume it doesn't + * need to actually check value in memory when used and may miss changes from + * signal handlers. + */ +volatile char dispatchException = 0; +volatile char isItTimeToYield; + +/* Various of the DIX function interfaces were not designed to allow + * the client->errorValue to be set on BadValue and other errors. + * Rather than changing interfaces and breaking untold code we introduce + * a new global that dispatch can use. + */ +XID clientErrorValue; /* XXX this is a kludge */ + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime() +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf() +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + +void +InitSelections() +{ + if (CurrentSelections) + xfree(CurrentSelections); + CurrentSelections = (Selection *)NULL; + NumCurrentSelections = 0; +} + +void +FlushClientCaches(XID id) +{ + int i; + register ClientPtr client; + + client = clients[CLIENT_ID(id)]; + if (client == NullClient) + return ; + for (i=0; ilastDrawableID == id) + { + client->lastDrawableID = WindowTable[0]->drawable.id; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + } + else if (client->lastGCID == id) + { + client->lastGCID = INVALID; + client->lastGC = (GCPtr)NULL; + } + } + } +} +#ifdef SMART_SCHEDULE + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +Bool SmartScheduleDisable = FALSE; +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +ClientPtr SmartLastClient; +int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; +int SmartScheduleClient(int *clientReady, int nready); + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); +void InitProcVectors(void); + +int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} +#endif + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + register int *clientReady; /* array of request ready clients */ + register int result; + register ClientPtr client; + register int nready; + register HWEventQueuePtr* icheck = checkForInput; +#ifdef SMART_SCHEDULE + long start_tick; +#endif + + nextFreeClientID = 1; + InitSelections(); + nClients = 0; + + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); + if (!clientReady) + return; + + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + nready = WaitForSomething(clientReady); + +#ifdef SMART_SCHEDULE + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } +#endif + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + requestingClient = client; +#ifdef SMART_SCHEDULE + start_tick = SmartScheduleTime; +#endif + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } +#endif + /* now, finally, deal with client requests */ + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } + + client->sequence++; +#ifdef DEBUG + if (client->requestLogIndex == MAX_REQUEST_LOG) + client->requestLogIndex = 0; + client->requestLog[client->requestLogIndex] = MAJOROP; + client->requestLogIndex++; +#endif + if (result > (maxBigRequestSize << 2)) + result = BadLength; + else + result = (* client->requestVector[MAJOROP])(client); + + if (result != Success) + { + if (client->noClientException != Success) + CloseDownClient(client); + else + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } +#ifdef DAMAGEEXT + FlushIfCriticalOutputPending (); +#endif + } + FlushAllOutput(); +#ifdef SMART_SCHEDULE + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; +#endif + requestingClient = NULL; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } +#if defined(DDXBEFORERESET) + ddxBeforeReset (); +#endif + KillAllClients(); + DEALLOCATE_LOCAL(clientReady); + dispatchException &= ~DE_RESET; +} + +#undef MAJOROP + +int +ProcBadRequest(ClientPtr client) +{ + return (BadRequest); +} + +int +ProcCreateWindow(ClientPtr client) +{ + register WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int result; + int len; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + if (!(pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess))) + return BadWindow; + len = client->req_len - (sizeof(xCreateWindowReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &result); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcChangeWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + result = ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcGetWindowAttributes(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return(client->noClientException); +} + +int +ProcDestroyWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + if (pWin->parent) + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcDestroySubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityDestroyAccess); + if (!pWin) + return(BadWindow); + DestroySubwindows(pWin, client); + return(client->noClientException); +} + +int +ProcChangeSaveSet(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + register int result; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + { + result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->mode; + return( BadValue ); + } +} + +int +ProcReparentWindow(register ClientPtr client) +{ + register WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + register int result; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, + SecurityWriteAccess); + if (!pParent) + return(BadWindow); + if (SAME_SCREENS(pWin->drawable, pParent->drawable)) + { + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + result = ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + return (BadMatch); +} + +int +ProcMapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcMapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + return(client->noClientException); +} + +int +ProcUnmapSubwindows(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + UnmapSubwindows(pWin); + return(client->noClientException); +} + +int +ProcConfigureWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xConfigureWindowReq); + register int result; + int len; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + pWin = (WindowPtr)SecurityLookupWindow( stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + len = client->req_len - (sizeof(xConfigureWindowReq) >> 2); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], + client); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcCirculateWindow(register ClientPtr client) +{ + register WindowPtr pWin; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + CirculateWindow(pWin, (int)stuff->direction, client); + return(client->noClientException); +} + +int +GetGeometry(register ClientPtr client, xGetGeometryReply *rep) +{ + register DrawablePtr pDraw; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->id, client, SecurityReadAccess); + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + /* XXX - Because the pixmap-implementation of the multibuffer extension + * may have the buffer-id's drawable resource value be a pointer + * to the buffer's window instead of the buffer itself + * (this happens if the buffer is the displayed buffer), + * we also have to check that the id matches before we can + * truly say that it is a DRAWABLE_WINDOW. + */ + + if ((pDraw->type == UNDRAWABLE_WINDOW) || + ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) + { + register WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(register ClientPtr client) +{ + xGetGeometryReply rep; + int status; + + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return(client->noClientException); +} + + +int +ProcQueryTree(register ClientPtr client) +{ + xQueryTreeReply reply; + int numChildren = 0; + register WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + reply.type = X_Reply; + reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + numChildren++; + if (numChildren) + { + int curChild = 0; + + childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + childIDs[curChild++] = pChild->drawable.id; + } + + reply.nChildren = numChildren; + reply.length = (numChildren * sizeof(Window)) >> 2; + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + DEALLOCATE_LOCAL(childIDs); + } + + return(client->noClientException); +} + +int +ProcInternAtom(register ClientPtr client) +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return(BadValue); + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return(client->noClientException); + } + else + return (BadAlloc); +} + +int +ProcGetAtomName(register ClientPtr client) +{ + char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + reply.type = X_Reply; + reply.length = (len + 3) >> 2; + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +#ifdef K5AUTH +extern int k5_bad(); +#endif + +int +ProcSetSelectionOwner(register ClientPtr client) +{ + WindowPtr pWin; + TimeStamp time; + REQUEST(xSetSelectionOwnerReq); + + REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); + UpdateCurrentTime(); + time = ClientTimeToServerTime(stuff->time); + + /* If the client's time stamp is in the future relative to the server's + time stamp, do not set the selection, just return success. */ + if (CompareTimeStamps(time, currentTime) == LATER) + return Success; + if (stuff->window != None) + { + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + } + else + pWin = (WindowPtr)None; + if (ValidAtom(stuff->selection)) + { + int i = 0; + + /* + * First, see if the selection is already set... + */ + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) + i++; + if (i < NumCurrentSelections) + { + xEvent event; + + /* If the timestamp in client's request is in the past relative + to the time stamp indicating the last time the owner of the + selection was set, do not set the selection, just return + success. */ + if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged) + == EARLIER) + return Success; + if (CurrentSelections[i].client && + (!pWin || (CurrentSelections[i].client != client))) + { + event.u.u.type = SelectionClear; + event.u.selectionClear.time = time.milliseconds; + event.u.selectionClear.window = CurrentSelections[i].window; + event.u.selectionClear.atom = CurrentSelections[i].selection; + (void) TryClientEvents (CurrentSelections[i].client, &event, 1, + NoEventMask, NoEventMask /* CantBeFiltered */, + NullGrab); + } + } + else + { + /* + * It doesn't exist, so add it... + */ + Selection *newsels; + + if (i == 0) + newsels = (Selection *)xalloc(sizeof(Selection)); + else + newsels = (Selection *)xrealloc(CurrentSelections, + (NumCurrentSelections + 1) * sizeof(Selection)); + if (!newsels) + return BadAlloc; + NumCurrentSelections++; + CurrentSelections = newsels; + CurrentSelections[i].selection = stuff->selection; + } + CurrentSelections[i].lastTimeChanged = time; + CurrentSelections[i].window = stuff->window; + CurrentSelections[i].pWin = pWin; + CurrentSelections[i].client = (pWin ? client : NullClient); + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind= SelectionSetOwner; + CallCallbacks(&SelectionCallback, &info); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->selection; + return (BadAtom); + } +} + +int +ProcGetSelectionOwner(register ClientPtr client) +{ + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if (ValidAtom(stuff->id)) + { + int i; + xGetSelectionOwnerReply reply; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->id) i++; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + if (i < NumCurrentSelections) + reply.owner = CurrentSelections[i].window; + else + reply.owner = None; + WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadAtom); + } +} + +int +ProcConvertSelection(register ClientPtr client) +{ + Bool paramsOkay; + xEvent event; + WindowPtr pWin; + REQUEST(xConvertSelectionReq); + + REQUEST_SIZE_MATCH(xConvertSelectionReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); + if (stuff->property != None) + paramsOkay &= ValidAtom(stuff->property); + if (paramsOkay) + { + int i; + + i = 0; + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + if ((i < NumCurrentSelections) && + (CurrentSelections[i].window != None) +#ifdef XCSECURITY + && (!client->CheckAccess || + (* client->CheckAccess)(client, CurrentSelections[i].window, + RT_WINDOW, SecurityReadAccess, + CurrentSelections[i].pWin)) +#endif + ) + { + event.u.u.type = SelectionRequest; + event.u.selectionRequest.time = stuff->time; + event.u.selectionRequest.owner = + CurrentSelections[i].window; + event.u.selectionRequest.requestor = stuff->requestor; + event.u.selectionRequest.selection = stuff->selection; + event.u.selectionRequest.target = stuff->target; + event.u.selectionRequest.property = stuff->property; + if (TryClientEvents( + CurrentSelections[i].client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab)) + return (client->noClientException); + } + event.u.u.type = SelectionNotify; + event.u.selectionNotify.time = stuff->time; + event.u.selectionNotify.requestor = stuff->requestor; + event.u.selectionNotify.selection = stuff->selection; + event.u.selectionNotify.target = stuff->target; + event.u.selectionNotify.property = None; + (void) TryClientEvents(client, &event, 1, NoEventMask, + NoEventMask /* CantBeFiltered */, NullGrab); + return (client->noClientException); + } + else + { + client->errorValue = stuff->property; + return (BadAtom); + } +} + +int +ProcGrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return(client->noClientException); + } + OnlyListenToOneClient(client); + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return(client->noClientException); +} + +static void +UngrabServer(ClientPtr client) +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(register ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return(client->noClientException); +} + +int +ProcTranslateCoords(register ClientPtr client) +{ + REQUEST(xTranslateCoordsReq); + + register WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->srcWid, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + pDst = (WindowPtr)SecurityLookupWindow(stuff->dstWid, client, + SecurityReadAccess); + if (!pDst) + return(BadWindow); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { +#ifdef SHAPE + BoxRec box; +#endif + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + &pWin->borderSize, x, y, &box)) + + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return(client->noClientException); +} + +int +ProcOpenFont(register ClientPtr client) +{ + int err; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcCloseFont(register ClientPtr client) +{ + FontPtr pFont; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityDestroyAccess); + if ( pFont != (FontPtr)NULL) /* id was valid */ + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadFont); + } +} + +int +ProcQueryFont(register ClientPtr client) +{ + xQueryFontReply *reply; + FontPtr pFont; + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + client->errorValue = stuff->id; /* EITHER font or gc */ + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->id; + return(BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); + if(!reply) + { + return(BadAlloc); + } + + reply->type = X_Reply; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + DEALLOCATE_LOCAL(reply); + return(client->noClientException); + } +} + +int +ProcQueryTextExtents(register ClientPtr client) +{ + REQUEST(xQueryTextExtentsReq); + xQueryTextExtentsReply reply; + FontPtr pFont; + GC *pGC; + ExtentInfoRec info; + unsigned long length; + + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + pFont = (FontPtr)SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + pGC = (GC *)SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC) + { + client->errorValue = stuff->fid; + return(BadFont); + } + pFont = pGC->font; + } + length = client->req_len - (sizeof(xQueryTextExtentsReq) >> 2); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return(BadLength); + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return(BadAlloc); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return(client->noClientException); +} + +int +ProcListFonts(register ClientPtr client) +{ + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(register ClientPtr client) +{ + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/** + * + * \param value must conform to DeleteType + */ +int +dixDestroyPixmap(pointer value, XID pid) +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + register int i; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->width > 32767 || stuff->height > 32767) + { + /* It is allowed to try and allocate a pixmap which is larger than + * 32767 in either dimension. However, all of the framebuffer code + * is buggy and does not reliably draw to such big pixmaps, basically + * because the Region data structure operates with signed shorts + * for the rectangles in it. + * + * Furthermore, several places in the X server computes the + * size in bytes of the pixmap and tries to store it in an + * integer. This integer can overflow and cause the allocated size + * to be much smaller. + * + * So, such big pixmaps are rejected here with a BadAlloc + */ + return BadAlloc; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return(client->noClientException); + } + return (BadAlloc); +} + +int +ProcFreePixmap(register ClientPtr client) +{ + PixmapPtr pMap; + + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP, + SecurityDestroyAccess); + if (pMap) + { + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadPixmap); + } +} + +int +ProcCreateGC(register ClientPtr client) +{ + int error; + GC *pGC; + register DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + SECURITY_VERIFY_DRAWABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + len = client->req_len - (sizeof(xCreateGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, + (XID *) &stuff[1], &error); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return (BadAlloc); + return(client->noClientException); +} + +int +ProcChangeGC(register ClientPtr client) +{ + GC *pGC; + REQUEST(xChangeGCReq); + int result; + unsigned len; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess); + len = client->req_len - (sizeof(xChangeGCReq) >> 2); + if (len != Ones(stuff->mask)) + return BadLength; + + result = dixChangeGC(client, pGC, stuff->mask, (CARD32 *) &stuff[1], 0); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcCopyGC(register ClientPtr client) +{ + register GC *dstGC; + register GC *pGC; + int result; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + SECURITY_VERIFY_GC( pGC, stuff->srcGC, client, SecurityReadAccess); + SECURITY_VERIFY_GC( dstGC, stuff->dstGC, client, SecurityWriteAccess); + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return (BadMatch); + result = CopyGC(pGC, dstGC, stuff->mask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetDashes(register ClientPtr client) +{ + register GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + result = SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(result); + } +} + +int +ProcSetClipRectangles(register ClientPtr client) +{ + int nr; + int result; + register GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + SECURITY_VERIFY_GC(pGC,stuff->gc, client, SecurityWriteAccess); + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return(BadLength); + nr >>= 3; + result = SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +int +ProcFreeGC(register ClientPtr client) +{ + register GC *pGC; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + SECURITY_VERIFY_GC(pGC, stuff->id, client, SecurityDestroyAccess); + FreeResource(stuff->id, RT_NONE); + return(client->noClientException); +} + +int +ProcClearToBackground(register ClientPtr client) +{ + REQUEST(xClearAreaReq); + register WindowPtr pWin; + + REQUEST_SIZE_MATCH(xClearAreaReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return (BadMatch); + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return(BadValue); + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return(client->noClientException); +} + +int +ProcCopyArea(register ClientPtr client) +{ + register DrawablePtr pDst; + register DrawablePtr pSrc; + register GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client, + SecurityReadAccess); + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + pSrc = pDst; + + SET_DBE_SRCBUF(pSrc, stuff->srcDrawable); + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + REGION_DESTROY(pDst->pScreen, pRgn); + } + + return(client->noClientException); +} + +int +ProcCopyPlane(register ClientPtr client) +{ + register DrawablePtr psrcDraw, pdstDraw; + register GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); + if (stuff->dstDrawable != stuff->srcDrawable) + { + SECURITY_VERIFY_DRAWABLE(psrcDraw, stuff->srcDrawable, client, + SecurityReadAccess); + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return (BadMatch); + } + } + else + psrcDraw = pdstDraw; + + SET_DBE_SRCBUF(psrcDraw, stuff->srcDrawable); + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + REGION_DESTROY(pdstDraw->pScreen, pRgn); + } + return(client->noClientException); +} + +int +ProcPolyPoint(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; + if (npoint) + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyLine(register ClientPtr client) +{ + int npoint; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; + if (npoint > 1) + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolySegment(register ClientPtr client) +{ + int nsegs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return(BadLength); + nsegs >>= 3; + if (nsegs) + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyRectangle (register ClientPtr client) +{ + int nrects; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return(BadLength); + nrects >>= 3; + if (nrects) + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +int +ProcFillPoly(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; + if (things) + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + return(client->noClientException); +} + +int +ProcPolyFillRectangle(register ClientPtr client) +{ + int things; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return(BadLength); + things >>= 3; + + if (things) + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + return (client->noClientException); +} + +int +ProcPolyFillArc(register ClientPtr client) +{ + int narcs; + register GC *pGC; + register DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return(BadLength); + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + return (client->noClientException); +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(register ClientPtr client) +{ + register GC *pGC; + register DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if (((((lengthProto * stuff->height) + (unsigned)3) >> 2) + + (sizeof(xPutImageReq) >> 2)) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return (client->noClientException); +} + + +int +DoGetImage(register ClientPtr client, int format, Drawable drawable, + int x, int y, int width, int height, + Mask planemask, xGetImageReply **im_return) +{ + register DrawablePtr pDraw; + int nlines, linesPerBuf; + register int linesDone; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; +#ifdef XCSECURITY + RegionPtr pVisibleRegion = NULL; +#endif + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return(BadValue); + } + SECURITY_VERIFY_DRAWABLE(pDraw, drawable, client, SecurityReadAccess); + if(pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + x < 0 || + pDraw->x + x + width > pDraw->pScreen->width || + pDraw->y + y < 0 || + pDraw->y + y + height > pDraw->pScreen->height || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + width > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + height > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual (((WindowPtr) pDraw)); + } + else + { + if(x < 0 || + x+width > (int)pDraw->width || + y < 0 || + y+height > (int)pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + + SET_DBE_SRCBUF(pDraw, drawable); + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = (char *)xalloc(sz_xGetImageReply + length); + if (!pBuf) + return (BadAlloc); + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = (xgi.length + 3) >> 2; + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = (char *) ALLOCATE_LOCAL(length))) + return (BadAlloc); + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + +#ifdef XCSECURITY + if (client->trustLevel != XSecurityClientTrusted && + pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion, -pDraw->x, -pDraw->y); + } + } +#endif + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); +#ifdef XCSECURITY + if (pVisibleRegion) + SecurityCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); +#endif + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } +#ifdef XCSECURITY + if (pVisibleRegion) + REGION_DESTROY(pDraw->pScreen, pVisibleRegion); +#endif + if (!im_return) + DEALLOCATE_LOCAL(pBuf); + return (client->noClientException); +} + +int +ProcGetImage(register ClientPtr client) +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(register ClientPtr client) +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText8(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + +int +ProcImageText16(register ClientPtr client) +{ + int err; + register DrawablePtr pDraw; + register GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return(client->noClientException); + } + else + return err; +} + + +int +ProcCreateColormap(register ClientPtr client) +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + register WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return(BadValue); + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + result = CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + client->errorValue = stuff->visual; + return(BadValue); +} + +int +ProcFreeColormap(register ClientPtr client) +{ + ColormapPtr pmap; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pmap = (ColormapPtr )SecurityLookupIDByType(client, stuff->id, RT_COLORMAP, + SecurityDestroyAccess); + if (pmap) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + + +int +ProcCopyColormapAndFree(register ClientPtr client) +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int result; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + if( (pSrcMap = (ColormapPtr )SecurityLookupIDByType(client, stuff->srcCmap, + RT_COLORMAP, SecurityReadAccess|SecurityWriteAccess)) ) + { + result = CopyColormapAndFree(mid, pSrcMap, client->index); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); + } + else + { + client->errorValue = stuff->srcCmap; + return(BadColor); + } +} + +int +ProcInstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcUninstallColormap(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->id, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadColor); + } +} + +int +ProcListInstalledColormaps(register ClientPtr client) +{ + xListInstalledColormapsReply *preply; + int nummaps; + WindowPtr pWin; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + + if (!pWin) + return(BadWindow); + + preply = (xListInstalledColormapsReply *) + ALLOCATE_LOCAL(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return(BadAlloc); + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + DEALLOCATE_LOCAL(preply); + return(client->noClientException); +} + +int +ProcAllocColor (register ClientPtr client) +{ + ColormapPtr pmap; + int retval; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + pmap = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pmap) + { +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pmap, (xReq *) stuff)) + return Success; +#endif + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (retval = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return (retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return (client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int retval; + + xAllocNamedColorReply ancr; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocNamedColor request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (retval = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + { + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return (client->noClientException); + } + else + return(BadName); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorCells (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorCellsReply accr; + int npixels, nmasks, retval; + long length; + Pixel *ppixels, *pmasks; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorCells request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + pmasks = ppixels + npixels; + + if( (retval = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = length >> 2; + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcAllocColorPlanes(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xAllocColorPlanesReply acpr; + int npixels, retval; + long length; + Pixel *ppixels; + +#ifdef LBX + /* + * If the colormap is grabbed by a proxy, the server will have + * to regain control over the colormap. This AllocColorPlanes request + * will be handled after the server gets back the colormap control. + */ + if (LbxCheckColorRequest (client, pcmp, (xReq *) stuff)) + return Success; +#endif + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return (BadValue); + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return (BadValue); + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = (Pixel *)ALLOCATE_LOCAL(length); + if(!ppixels) + return(BadAlloc); + if( (retval = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + DEALLOCATE_LOCAL(ppixels); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + acpr.length = length >> 2; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + DEALLOCATE_LOCAL(ppixels); + return (client->noClientException); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcFreeColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + if(pcmp->flags & AllAllocated) + return(BadAccess); + count = ((client->req_len << 2)- sizeof(xFreeColorsReq)) >> 2; + retval = FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreColors (ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + int count; + int retval; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return(BadLength); + count /= sizeof(xColorItem); + retval = StoreColors(pcmp, count, (xColorItem *)&stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return(retval); + } + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcStoreNamedColor (register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityWriteAccess); + if (pcmp) + { + xColorItem def; + int retval; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + retval = StoreColors(pcmp, 1, &def); + if (client->noClientException != Success) + return(client->noClientException); + else + return(retval); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcQueryColors(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + int count, retval; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = ((client->req_len << 2) - sizeof(xQueryColorsReq)) >> 2; + prgbs = (xrgb *)ALLOCATE_LOCAL(count * sizeof(xrgb)); + if(!prgbs && count) + return(BadAlloc); + if( (retval = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs)) ) + { + if (prgbs) DEALLOCATE_LOCAL(prgbs); + if (client->noClientException != Success) + return(client->noClientException); + else + { + client->errorValue = clientErrorValue; + return (retval); + } + } + qcr.type = X_Reply; + qcr.length = (count * sizeof(xrgb)) >> 2; + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + if (prgbs) DEALLOCATE_LOCAL(prgbs); + return(client->noClientException); + + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcLookupColor(register ClientPtr client) +{ + ColormapPtr pcmp; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + pcmp = (ColormapPtr)SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, SecurityReadAccess); + if (pcmp) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return(client->noClientException); + } + return (BadName); + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + +int +ProcCreateCursor (register ClientPtr client) +{ + CursorPtr pCursor; + + register PixmapPtr src; + register PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + src = (PixmapPtr)SecurityLookupIDByType(client, stuff->source, + RT_PIXMAP, SecurityReadAccess); + msk = (PixmapPtr)SecurityLookupIDByType(client, stuff->mask, + RT_PIXMAP, SecurityReadAccess); + if ( src == (PixmapPtr)NULL) + { + client->errorValue = stuff->source; + return (BadPixmap); + } + if ( msk == (PixmapPtr)NULL) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return (BadPixmap); + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return (BadMatch); + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + + n = BitmapBytePad(width)*height; + srcbits = (unsigned char *)xalloc(n); + if (!srcbits) + return (BadAlloc); + mskbits = (unsigned char *)xalloc(n); + if (!mskbits) + { + xfree(srcbits); + return (BadAlloc); + } + + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)srcbits, n); + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + register unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + bzero((char *)mskbits, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursor( srcbits, mskbits, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue); + + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +int +ProcCreateGlyphCursor (register ClientPtr client) +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + + +int +ProcFreeCursor (register ClientPtr client) +{ + CursorPtr pCursor; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->id, + RT_CURSOR, SecurityDestroyAccess); + if (pCursor) + { + FreeResource(stuff->id, RT_NONE); + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadCursor); + } +} + +int +ProcQueryBestSize (register ClientPtr client) +{ + xQueryBestSizeReply reply; + register DrawablePtr pDraw; + ScreenPtr pScreen; + REQUEST(xQueryBestSizeReq); + + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return(BadValue); + } + SECURITY_VERIFY_GEOMETRABLE (pDraw, stuff->drawable, client, + SecurityReadAccess); + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return (BadMatch); + pScreen = pDraw->pScreen; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return (client->noClientException); +} + + +int +ProcSetScreenSaver (register ClientPtr client) +{ + int blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + if (blankingOption == DefaultBlanking) + ScreenSaverBlanking = defaultScreenSaverBlanking; + else + ScreenSaverBlanking = blankingOption; + if (exposureOption == DefaultExposures) + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + else + ScreenSaverAllowExposures = exposureOption; + + if (stuff->timeout >= 0) + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + else + ScreenSaverTime = defaultScreenSaverTime; + if (stuff->interval >= 0) + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + else + ScreenSaverInterval = defaultScreenSaverInterval; + + SetScreenSaverTimer(); + return (client->noClientException); +} + +int +ProcGetScreenSaver(register ClientPtr client) +{ + xGetScreenSaverReply rep; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return (client->noClientException); +} + +int +ProcChangeHosts(register ClientPtr client) +{ + REQUEST(xChangeHostsReq); + int result; + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + result = AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else if (stuff->mode == HostDelete) + result = RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + else + { + client->errorValue = stuff->mode; + return BadValue; + } + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcListHosts(register ClientPtr client) +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); +#ifdef XCSECURITY + /* untrusted clients can't list hosts */ + if (client->trustLevel != XSecurityClientTrusted) + { + SecurityAudit("client %d attempted to list hosts\n", client->index); + return BadAccess; + } +#endif + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return(result); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = len >> 2; + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + xfree(pdata); + return (client->noClientException); +} + +int +ProcChangeAccessControl(register ClientPtr client) +{ + int result; + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + result = ChangeAccessControl(client, stuff->mode == EnableAccess); + if (!result) + result = client->noClientException; + return (result); +} + +int +ProcKillClient(register ClientPtr client) +{ + REQUEST(xResourceReq); + ClientPtr killclient; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return (client->noClientException); + } + + if ((killclient = LookupClient(stuff->id, client))) + { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return (Success); + } + return (client->noClientException); + } + else + { + client->errorValue = stuff->id; + return (BadValue); + } +} + +int +ProcSetFontPath(register ClientPtr client) +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n, result; + int error; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return(BadLength); + total -= n; + ptr += n; + } + if (total >= 4) + return(BadLength); + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], + &error); + if (!result) + { + result = client->noClientException; + client->errorValue = error; + } + return (result); +} + +int +ProcGetFontPath(register ClientPtr client) +{ + xGetFontPathReply reply; + int stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + bufferStart = GetFontPath(&numpaths, &stringLens); + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = (stringLens + numpaths + 3) >> 2; + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return(client->noClientException); +} + +int +ProcChangeCloseDownMode(register ClientPtr client) +{ + REQUEST(xSetCloseDownModeReq); + + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return (client->noClientException); + } + else + { + client->errorValue = stuff->mode; + return (BadValue); + } +} + +int ProcForceScreenSaver(register ClientPtr client) +{ + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + return client->noClientException; +} + +int ProcNoOperation(register ClientPtr client) +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return(client->noClientException); +} + +void +InitProcVectors(void) +{ + int i; + for (i = 0; i<256; i++) + { + if(!ProcVector[i]) + { + ProcVector[i] = SwappedProcVector[i] = ProcBadRequest; + ReplySwapVector[i] = ReplyNotSwappd; + } +#ifdef K5AUTH + if (!k5_Vector[i]) + { + k5_Vector[i] = k5_bad; + } +#endif + } + for(i = LASTEvent; i < 128; i++) + { + EventSwapVector[i] = NotImplemented; + } + +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +char dispatchExceptionAtReset = DE_RESET; + +void +CloseDownClient(register ClientPtr client) +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); +#ifdef LBX + ProcessQTagZombies(); +#endif + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; +#ifdef SMART_SCHEDULE + SmartLastClient = NullClient; +#endif + xfree(client); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients() +{ + int i; + for (i=1; icloseDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +void +CloseDownRetainedResources() +{ + register int i; + register ClientPtr client; + + for (i=1; icloseDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +void InitClient(ClientPtr client, int i, pointer ospriv) +{ + client->index = i; + client->sequence = 0; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->clientGone = FALSE; + if (i) + { + client->closeDownMode = DestroyAll; + client->lastDrawable = (DrawablePtr)WindowTable[0]; + client->lastDrawableID = WindowTable[0]->drawable.id; + } + else + { + client->closeDownMode = RetainPermanent; + client->lastDrawable = (DrawablePtr)NULL; + client->lastDrawableID = INVALID; + } + client->lastGC = (GCPtr) NULL; + client->lastGCID = INVALID; + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; + client->noClientException = Success; +#ifdef DEBUG + client->requestLogIndex = 0; +#endif + client->requestVector = InitialVector; + client->osPrivate = ospriv; + client->swapped = FALSE; + client->big_requests = FALSE; + client->priority = 0; + client->clientState = ClientStateInitial; +#ifdef XKB + if (!noXkbExtension) { + client->xkbClientFlags = 0; + client->mapNotifyMask = 0; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + } +#endif + client->replyBytesRemaining = 0; +#ifdef LBX + client->readRequest = StandardReadRequestFromClient; +#endif +#ifdef XCSECURITY + client->trustLevel = XSecurityClientTrusted; + client->CheckAccess = NULL; + client->authId = 0; +#endif +#ifdef XAPPGROUP + client->appgroup = NULL; +#endif + client->fontResFunc = NULL; +#ifdef SMART_SCHEDULE + client->smart_priority = 0; + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; +#endif +} + +extern int clientPrivateLen; +extern unsigned *clientPrivateSizes; +extern unsigned totalClientSize; + +int +InitClientPrivates(ClientPtr client) +{ + register char *ptr; + DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + if (totalClientSize == sizeof(ClientRec)) + ppriv = (DevUnion *)NULL; + else if (client->index) + ppriv = (DevUnion *)(client + 1); + else + { + ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec)); + if (!ppriv) + return 0; + } + client->devPrivates = ppriv; + sizes = clientPrivateSizes; + ptr = (char *)(ppriv + clientPrivateLen); + for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return 1; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr NextAvailableClient(pointer ospriv) +{ + register int i; + register ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = (ClientPtr)xalloc(totalClientSize); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + InitClientPrivates(client); + if (!InitClientResources(client)) + { + xfree(client); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = (sz_xReq + sz_xConnClientPrefix) >> 2; + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + xfree(client); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return(client); +} + +int +ProcInitialConnection(register ClientPtr client) +{ + REQUEST(xReq); + register xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return (client->noClientException = -1); + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += ((prefix->nbytesAuthProto + (unsigned)3) >> 2) + + ((prefix->nbytesAuthString + (unsigned)3) >> 2); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return (client->noClientException); +} + +#ifdef LBX +void +IncrementClientCount() +{ + nClients++; +} +#endif + +int +SendConnSetup(register ClientPtr client, char *reason) +{ + register xWindowRoot *root; + register int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = (csp.lengthReason + (unsigned)3) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return (client->noClientException = -1); + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; +#ifdef XAPPGROUP + XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); +#endif + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; icurrentInputMask = WindowTable[i]->eventMask | + wOtherEventMasks (WindowTable[i]); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return (client->noClientException); +} + +int +ProcEstablishConnection(register ClientPtr client) +{ + char *reason, *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return(client->noClientException); +} + +void +SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, + XID resId, int errorCode) +{ + xError rep; + + rep.type = X_Error; + rep.sequenceNumber = client->sequence; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +DeleteWindowFromAnySelections(WindowPtr pWin) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].pWin == pWin) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +static void +DeleteClientFromAnySelections(ClientPtr client) +{ + register int i; + + for (i = 0; i< NumCurrentSelections; i++) + if (CurrentSelections[i].client == client) + { + if (SelectionCallback) + { + SelectionInfoRec info; + + info.selection = &CurrentSelections[i]; + info.kind = SelectionWindowDestroy; + CallCallbacks(&SelectionCallback, &info); + } + CurrentSelections[i].pWin = (WindowPtr)NULL; + CurrentSelections[i].window = None; + CurrentSelections[i].client = NullClient; + } +} + +void +MarkClientException(ClientPtr client) +{ + client->noClientException = -1; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c new file mode 100644 index 000000000..6dfff3776 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c @@ -0,0 +1,2797 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/dixfonts.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.28 2003/11/08 02:02:03 dawes Exp $ */ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ +/* The panoramix components contained the following notice */ +/* +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ +/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */ + +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +/* +#define NXAGENT_DEBUG +*/ + +#ifdef DEBUG +#include +#endif + +#include "Agent.h" +#include "Font.h" + +#ifndef NX_TRANS_SOCKET + +#define NX_TRANS_SOCKET + +#endif + +#ifdef NX_TRANS_SOCKET + +char _NXFontPath[1024]; + +/* + * Override the default font path and make + * it configurable at run time, based on + * the NX_FONT environment. + */ + +static const char *_NXGetFontPath(const char *path) +{ + const char *fontEnv; + + /* + * Check the environment only once. + */ + + if (*_NXFontPath != '\0') + { + return _NXFontPath; + } + + fontEnv = getenv("NX_FONT"); + + if (fontEnv != NULL && *fontEnv != '\0') + { + if (strlen(fontEnv) + 1 > 1024) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n"); +#endif + goto _NXGetFontPathError; + } + + strcpy(_NXFontPath, fontEnv); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; + } + +_NXGetFontPathError: + + strcpy(_NXFontPath, path); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; +} + +#endif + +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif + +#ifdef LBX +#include "lbxserve.h" +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + return BadName; + case BadFontPath: + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(char *defaultfontname) +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(FontPathElementPtr fpe) +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(FontPathElementPtr fpe) +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +void +FontWakeup(pointer data, int count, pointer LastSelectMask) +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +UseFPE(FontPathElementPtr fpe) +{ + fpe->refcount++; +} + +static void +FreeFPE (FontPathElementPtr fpe) +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +doOpenFont(ClientPtr client, OFclosurePtr c) +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe = NULL; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + char nxagentOrigFontName[256]; + int nxagentOrigFontNameLen; + + /* + * Decide at runtime what FontFormat to use. + */ + Mask FontFormat = + + ((screenInfo.imageByteOrder == LSBFirst) ? + BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | + + ((screenInfo.bitmapBitOrder == LSBFirst) ? + BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + + + nxagentOrigFontNameLen = (c -> origFontNameLen < 256) ? c -> origFontNameLen : 255; + + memcpy(nxagentOrigFontName, c -> origFontName, nxagentOrigFontNameLen); + + nxagentOrigFontName[nxagentOrigFontNameLen] = 0; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + + /* NXAGENT uses useless screen pointer to pass the original font name + * to realizeFont, could be a source of problems in the future. + */ + + if (!(*pScr->RealizeFont) ((ScreenPtr)nxagentOrigFontName, pfont)) + { + CloseFont (pfont, (Font) 0); + err=BadFontName; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if( nxagentFontPriv(pfont) -> mirrorID == 0 ) + { + extern RESTYPE RT_NX_FONT; + + nxagentFontPriv(pfont) -> mirrorID = FakeClientID(0); + if (!AddResource(nxagentFontPriv(pfont) -> mirrorID, RT_NX_FONT, (pointer) pfont)) { + FreeResource(c->fontid, RT_NONE); + err = AllocError; + goto bail; + } + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/** + * Decrement font's ref count, and free storage if ref count equals zero + * + * \param value must conform to DeleteType + */ +int +CloseFont(pointer value, XID fid) +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef LBX + LbxFreeFontTag(pfont); +#endif +#ifdef XF86BIGFONT + { + extern void XF86BigfontFreeFontShm(FontPtr); + XF86BigfontFreeFontShm(pfont); + } +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + +/** + * Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. + * + * \param pReply caller must allocate this storage + */ +void +QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + unsigned char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, + TwoD16Bit, &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +doListFontsAndAliases(ClientPtr client, LFclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount = 0; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (2): client [%lx] sleeping.\n", client); +#endif +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + memmove(resolved, tmpname, resolvedlen + 1); + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + { + /* dirty hack: don't list to client fonts not existing on the remote side */ + char tmp[256]; + + memcpy(tmp, names->names[i], names->length[i]); + tmp[ names->length[i] ] = 0; + + if (nxagentFontLookUp(tmp) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases:\n"); + fprintf(stderr, " removing font: %s \n", tmp); +#endif + reply.nFonts--; + stringLens -= names->length[i]; + continue; + } + } + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + if (resolved) xfree(resolved); + return TRUE; +} + +int +ListFonts(ClientPtr client, unsigned char *pattern, unsigned length, + unsigned max_names) +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount = 0; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsWithInfo, + c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + + if (nxagentFontLookUp(name) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases (with info):\n"); + fprintf(stderr, " removing font: %s \n", name); +#endif + continue; + } + + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, + int max_names) +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(ClientPtr client, register PTclosurePtr c) +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; + FontPathElementPtr fpe; + GC *origGC = NULL; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; + else + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doPolyText, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolyText (1): client [%lx] sleeping.\n", client); +#endif + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { +#ifdef PANORAMIX + if (noPanoramiXExtension || !c->pGC->pScreen->myNum) +#endif + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolytext: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, + unsigned char *endReq, int xorg, int yorg, int reqType, XID did) +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(ClientPtr client, register ITclosurePtr c) +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText (1): client [%lx] sleeping.\n", client); +#endif + + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, + unsigned char *data, int xorg, int yorg, int reqType, XID did) +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +DetermineFPEType(char *pathname) +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +FreeFontPath(FontPathElementPtr *list, int n, Bool force) +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) +{ + int i, err = 0; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe = NULL, *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) + { + len = (unsigned int) (*cp++); + + if (len == 0) + { + if (persist) + ErrorF ("Removing empty element from the valid list of fontpaths\n"); + err = BadValue; + } + else + { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) + { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) + { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + } + else + fpe = 0; + } + /* if error or can't do it, act like it's a new one */ + if (!fpe) + { + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) + { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) + { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err = BadValue; + else + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) + { + #ifndef NXAGENT_SERVER + if (persist) + { + ErrorF("Could not init font path element %s, removing from list!\n", + fpe->name); + } + #endif + xfree (fpe->name); + xfree (fpe); + } + } + } + if (err != Successful) + { + if (!persist) + goto bail; + } + else + { + fplist[valid_paths++] = fpe; + } + cp += len; + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--valid_paths >= 0) + FreeFPE(fplist[valid_paths]); + xfree(fplist); + return FontToXError(err); +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error) +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadValue; + } else { + err = SetFontPathElements(npaths, paths, error, FALSE); + } + return err; +} + +int +SetDefaultFontPath(char *path) +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ +#ifdef NX_TRANS_SOCKET + len = strlen(_NXGetFontPath(path)) + 1; +#else + len = strlen(path) + 1; +#endif + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; +#ifdef NX_TRANS_SOCKET + pp = (unsigned char *) _NXGetFontPath(path); +#else + pp = (unsigned char *) path; +#endif + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad, TRUE); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(int *count, int *length) +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +int +LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, unsigned char *data) +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(ClientPtr client) +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + +#ifndef KDRIVESERVER + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else +#endif + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); +#ifndef NOFONTSERVERACCESS + fs_register_fpe_functions(); +#endif + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (int *num) +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(XID id) +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(FontPtr pfont, Font id) +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(Font id) +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(ClientPtr client) +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +void +dump_char_ascii(CharInfoPtr cip) +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif + + +typedef struct +{ + LFclosurePtr c; + OFclosurePtr oc; +} nxFs,*nxFsPtr; + +static Bool +#if NeedFunctionPrototypes +nxdoListFontsAndAliases(ClientPtr client, nxFsPtr fss) +#else +nxdoListFontsAndAliases(client, fss) + ClientPtr client; + nxFsPtr fss; +#endif +{ + LFclosurePtr c=fss->c; + OFclosurePtr oc=fss->oc; + FontPathElementPtr fpe; + int err = Successful; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int i; + int aliascount = 0; + char tmp[256]; + tmp[0]=0; + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + { + memmove(resolved, tmpname, resolvedlen); + resolved[resolvedlen] = '\0'; + } + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + { + memcpy(tmp,c->savedName,c->savedNameLen>255?255:c->savedNameLen); + tmp[c->savedNameLen>255?256:c->savedNameLen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + else + { + memcpy(tmp,name,namelen>255?255:namelen); + tmp[namelen>255?256:namelen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + { + memmove(c->savedName, name, namelen); + c->savedName[namelen] = '\0'; + } + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ +bail: +finish: + if (strlen(tmp)) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (0) font to %s\n",tmp); +#endif + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + + } + else + { + for (i = 0; i < c->names->nnames; i++) + { + if (c->names->length[i] > 255) + continue; + else + { + memcpy(tmp, c->names->names[i], c->names->length[i]); + tmp[ c->names->length[i] ] = 0; + if (nxagentFontLookUp(tmp) == 0) + continue; + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (1) font to %s\n",tmp); +#endif + break; + } + } + } + + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(c->names); + xfree(c); + xfree(fss); + if (resolved) xfree(resolved); + + return doOpenFont(client, oc); +} + +int +nxOpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + nxFsPtr fss; + LFclosurePtr c; + OFclosurePtr oc; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + if (!(fss = (nxFsPtr) xalloc(sizeof(nxFs)))) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + { + xfree(fss); + return BadAlloc; + } + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + xfree(fss); + return BadAlloc; + } + c->names = MakeFontNamesRecord(100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove( c->current.pattern, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = lenfname; + c->current.current_fpe = 0; + c->current.max_names = nxagentMaxFontNames; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + + oc = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!oc) + { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + oc->fontname = (char *) xalloc(256);/* I don't want to deal with future reallocs errors */ + oc->origFontName = pfontname; + oc->origFontNameLen = lenfname; + if (!oc->fontname) { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(oc); + xfree(fss); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + oc->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!oc->fpe_list) { + xfree(oc->fontname); + xfree(oc); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove(oc->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + oc->fpe_list[i] = font_path_elements[i]; + UseFPE(oc->fpe_list[i]); + } + oc->client = client; + oc->fontid = fid; + oc->current_fpe = 0; + oc->num_fpes = num_fpes; + oc->fnamelen = lenfname; + oc->slept = FALSE; + oc->flags = flags; + oc->non_cachable_font = cached; + fss->c=c; + fss->oc=oc; + nxdoListFontsAndAliases(client, fss); + return Success; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.NX.original new file mode 100644 index 000000000..6dfff3776 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.NX.original @@ -0,0 +1,2797 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/dixfonts.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.28 2003/11/08 02:02:03 dawes Exp $ */ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ +/* The panoramix components contained the following notice */ +/* +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ +/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */ + +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +/* +#define NXAGENT_DEBUG +*/ + +#ifdef DEBUG +#include +#endif + +#include "Agent.h" +#include "Font.h" + +#ifndef NX_TRANS_SOCKET + +#define NX_TRANS_SOCKET + +#endif + +#ifdef NX_TRANS_SOCKET + +char _NXFontPath[1024]; + +/* + * Override the default font path and make + * it configurable at run time, based on + * the NX_FONT environment. + */ + +static const char *_NXGetFontPath(const char *path) +{ + const char *fontEnv; + + /* + * Check the environment only once. + */ + + if (*_NXFontPath != '\0') + { + return _NXFontPath; + } + + fontEnv = getenv("NX_FONT"); + + if (fontEnv != NULL && *fontEnv != '\0') + { + if (strlen(fontEnv) + 1 > 1024) + { +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n"); +#endif + goto _NXGetFontPathError; + } + + strcpy(_NXFontPath, fontEnv); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; + } + +_NXGetFontPathError: + + strcpy(_NXFontPath, path); + +#ifdef NX_TRANS_TEST + fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath); +#endif + + return _NXFontPath; +} + +#endif + +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif + +#ifdef LBX +#include "lbxserve.h" +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + return BadName; + case BadFontPath: + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(char *defaultfontname) +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(FontPathElementPtr fpe) +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(FontPathElementPtr fpe) +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +void +FontWakeup(pointer data, int count, pointer LastSelectMask) +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +UseFPE(FontPathElementPtr fpe) +{ + fpe->refcount++; +} + +static void +FreeFPE (FontPathElementPtr fpe) +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +doOpenFont(ClientPtr client, OFclosurePtr c) +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe = NULL; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + char nxagentOrigFontName[256]; + int nxagentOrigFontNameLen; + + /* + * Decide at runtime what FontFormat to use. + */ + Mask FontFormat = + + ((screenInfo.imageByteOrder == LSBFirst) ? + BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | + + ((screenInfo.bitmapBitOrder == LSBFirst) ? + BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + + + nxagentOrigFontNameLen = (c -> origFontNameLen < 256) ? c -> origFontNameLen : 255; + + memcpy(nxagentOrigFontName, c -> origFontName, nxagentOrigFontNameLen); + + nxagentOrigFontName[nxagentOrigFontNameLen] = 0; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + + /* NXAGENT uses useless screen pointer to pass the original font name + * to realizeFont, could be a source of problems in the future. + */ + + if (!(*pScr->RealizeFont) ((ScreenPtr)nxagentOrigFontName, pfont)) + { + CloseFont (pfont, (Font) 0); + err=BadFontName; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if( nxagentFontPriv(pfont) -> mirrorID == 0 ) + { + extern RESTYPE RT_NX_FONT; + + nxagentFontPriv(pfont) -> mirrorID = FakeClientID(0); + if (!AddResource(nxagentFontPriv(pfont) -> mirrorID, RT_NX_FONT, (pointer) pfont)) { + FreeResource(c->fontid, RT_NONE); + err = AllocError; + goto bail; + } + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/** + * Decrement font's ref count, and free storage if ref count equals zero + * + * \param value must conform to DeleteType + */ +int +CloseFont(pointer value, XID fid) +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef LBX + LbxFreeFontTag(pfont); +#endif +#ifdef XF86BIGFONT + { + extern void XF86BigfontFreeFontShm(FontPtr); + XF86BigfontFreeFontShm(pfont); + } +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + +/** + * Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. + * + * \param pReply caller must allocate this storage + */ +void +QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + unsigned char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, + TwoD16Bit, &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +doListFontsAndAliases(ClientPtr client, LFclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount = 0; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (2): client [%lx] sleeping.\n", client); +#endif +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + memmove(resolved, tmpname, resolvedlen + 1); + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + { + /* dirty hack: don't list to client fonts not existing on the remote side */ + char tmp[256]; + + memcpy(tmp, names->names[i], names->length[i]); + tmp[ names->length[i] ] = 0; + + if (nxagentFontLookUp(tmp) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases:\n"); + fprintf(stderr, " removing font: %s \n", tmp); +#endif + reply.nFonts--; + stringLens -= names->length[i]; + continue; + } + } + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + if (resolved) xfree(resolved); + return TRUE; +} + +int +ListFonts(ClientPtr client, unsigned char *pattern, unsigned length, + unsigned max_names) +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount = 0; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsWithInfo, + c); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + + if (nxagentFontLookUp(name) == 0) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "doListFontsAndAliases (with info):\n"); + fprintf(stderr, " removing font: %s \n", name); +#endif + continue; + } + + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doListFontWinfo: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, + int max_names) +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(ClientPtr client, register PTclosurePtr c) +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; + FontPathElementPtr fpe; + GC *origGC = NULL; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; + else + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doPolyText, + (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolyText (1): client [%lx] sleeping.\n", client); +#endif + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { +#ifdef PANORAMIX + if (noPanoramiXExtension || !c->pGC->pScreen->myNum) +#endif + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doPolytext: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, + unsigned char *endReq, int xorg, int yorg, int reqType, XID did) +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(ClientPtr client, register ITclosurePtr c) +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->stipple = NullPixmap; + + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText (1): client [%lx] sleeping.\n", client); +#endif + + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: doImageText: client [%lx] wakeup.\n", client); +#endif + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, + unsigned char *data, int xorg, int yorg, int reqType, XID did) +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +DetermineFPEType(char *pathname) +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +FreeFontPath(FontPathElementPtr *list, int n, Bool force) +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) +{ + int i, err = 0; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe = NULL, *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) + { + len = (unsigned int) (*cp++); + + if (len == 0) + { + if (persist) + ErrorF ("Removing empty element from the valid list of fontpaths\n"); + err = BadValue; + } + else + { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) + { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) + { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + } + else + fpe = 0; + } + /* if error or can't do it, act like it's a new one */ + if (!fpe) + { + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) + { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) + { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err = BadValue; + else + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) + { + #ifndef NXAGENT_SERVER + if (persist) + { + ErrorF("Could not init font path element %s, removing from list!\n", + fpe->name); + } + #endif + xfree (fpe->name); + xfree (fpe); + } + } + } + if (err != Successful) + { + if (!persist) + goto bail; + } + else + { + fplist[valid_paths++] = fpe; + } + cp += len; + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--valid_paths >= 0) + FreeFPE(fplist[valid_paths]); + xfree(fplist); + return FontToXError(err); +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error) +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadValue; + } else { + err = SetFontPathElements(npaths, paths, error, FALSE); + } + return err; +} + +int +SetDefaultFontPath(char *path) +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ +#ifdef NX_TRANS_SOCKET + len = strlen(_NXGetFontPath(path)) + 1; +#else + len = strlen(path) + 1; +#endif + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; +#ifdef NX_TRANS_SOCKET + pp = (unsigned char *) _NXGetFontPath(path); +#else + pp = (unsigned char *) path; +#endif + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad, TRUE); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(int *count, int *length) +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +int +LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, unsigned char *data) +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(ClientPtr client) +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + +#ifndef KDRIVESERVER + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else +#endif + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); +#ifndef NOFONTSERVERACCESS + fs_register_fpe_functions(); +#endif + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (int *num) +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(XID id) +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(FontPtr pfont, Font id) +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(Font id) +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(ClientPtr client) +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +void +dump_char_ascii(CharInfoPtr cip) +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif + + +typedef struct +{ + LFclosurePtr c; + OFclosurePtr oc; +} nxFs,*nxFsPtr; + +static Bool +#if NeedFunctionPrototypes +nxdoListFontsAndAliases(ClientPtr client, nxFsPtr fss) +#else +nxdoListFontsAndAliases(client, fss) + ClientPtr client; + nxFsPtr fss; +#endif +{ + LFclosurePtr c=fss->c; + OFclosurePtr oc=fss->oc; + FontPathElementPtr fpe; + int err = Successful; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int i; + int aliascount = 0; + char tmp[256]; + tmp[0]=0; + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (1): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (2): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)nxdoListFontsAndAliases, + (pointer) fss); + c->slept = TRUE; +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont (3): client [%lx] sleeping.\n", client); +#endif + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + { + memmove(resolved, tmpname, resolvedlen); + resolved[resolvedlen] = '\0'; + } + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + { + memcpy(tmp,c->savedName,c->savedNameLen>255?255:c->savedNameLen); + tmp[c->savedNameLen>255?256:c->savedNameLen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + else + { + memcpy(tmp,name,namelen>255?255:namelen); + tmp[namelen>255?256:namelen]=0; + if (nxagentFontLookUp(tmp)) + break; + else tmp[0]=0; + } + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + { + memmove(c->savedName, name, namelen); + c->savedName[namelen] = '\0'; + } + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ +bail: +finish: + if (strlen(tmp)) + { +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (0) font to %s\n",tmp); +#endif + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + + } + else + { + for (i = 0; i < c->names->nnames; i++) + { + if (c->names->length[i] > 255) + continue; + else + { + memcpy(tmp, c->names->names[i], c->names->length[i]); + tmp[ c->names->length[i] ] = 0; + if (nxagentFontLookUp(tmp) == 0) + continue; + memcpy(oc->fontname, tmp, strlen(tmp)); + oc->fnamelen = strlen(tmp); + + oc->origFontName = oc->fontname; + oc->origFontNameLen = oc->fnamelen; + +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "nxListFont changed (1) font to %s\n",tmp); +#endif + break; + } + } + } + + if (c->slept) + { + ClientWakeup(client); +#ifdef NXAGENT_DEBUG + fprintf(stderr, " NXdixfonts: nxdoListFont: client [%lx] wakeup.\n", client); +#endif + } + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(c->names); + xfree(c); + xfree(fss); + if (resolved) xfree(resolved); + + return doOpenFont(client, oc); +} + +int +nxOpenFont(client, fid, flags, lenfname, pfontname) + ClientPtr client; + XID fid; + Mask flags; + unsigned lenfname; + char *pfontname; +{ + nxFsPtr fss; + LFclosurePtr c; + OFclosurePtr oc; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + if (!(fss = (nxFsPtr) xalloc(sizeof(nxFs)))) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + { + xfree(fss); + return BadAlloc; + } + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + xfree(fss); + return BadAlloc; + } + c->names = MakeFontNamesRecord(100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove( c->current.pattern, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = lenfname; + c->current.current_fpe = 0; + c->current.max_names = nxagentMaxFontNames; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + + oc = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!oc) + { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + oc->fontname = (char *) xalloc(256);/* I don't want to deal with future reallocs errors */ + oc->origFontName = pfontname; + oc->origFontNameLen = lenfname; + if (!oc->fontname) { + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(oc); + xfree(fss); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + oc->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!oc->fpe_list) { + xfree(oc->fontname); + xfree(oc); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + xfree(c); + xfree(fss); + return BadAlloc; + } + memmove(oc->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + oc->fpe_list[i] = font_path_elements[i]; + UseFPE(oc->fpe_list[i]); + } + oc->client = client; + oc->fontid = fid; + oc->current_fpe = 0; + oc->num_fpes = num_fpes; + oc->fnamelen = lenfname; + oc->slept = FALSE; + oc->flags = flags; + oc->non_cachable_font = cached; + fss->c=c; + fss->oc=oc; + nxdoListFontsAndAliases(client, fss); + return Success; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original new file mode 100644 index 000000000..9de998417 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original @@ -0,0 +1,2143 @@ +/* $XdotOrg: xc/programs/Xserver/dix/dixfonts.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.28 2003/11/08 02:02:03 dawes Exp $ */ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ +/* The panoramix components contained the following notice */ +/* +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ +/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */ + +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "misc.h" +#include "opaque.h" +#include "dixfontstr.h" +#include "closestr.h" + +#ifdef DEBUG +#include +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#endif + +#ifdef LBX +#include "lbxserve.h" +#endif + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include +#endif + +#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics + +extern pointer fosNaturalParams; +extern FontPtr defaultFont; + +static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; +static int num_fpes = 0; +FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static int num_fpe_types = 0; + +static unsigned char *font_path_string; + +static int num_slept_fpes = 0; +static int size_slept_fpes = 0; +static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; +static FontPatternCachePtr patternCache; + +int +FontToXError(err) + int err; +{ + switch (err) { + case Successful: + return Success; + case AllocError: + return BadAlloc; + case BadFontName: + return BadName; + case BadFontPath: + case BadFontFormat: /* is there something better? */ + case BadCharRange: + return BadValue; + default: + return err; + } +} + + +/* + * adding RT_FONT prevents conflict with default cursor font + */ +Bool +SetDefaultFont(char *defaultfontname) +{ + int err; + FontPtr pf; + XID fid; + + fid = FakeClientID(0); + err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, + (unsigned) strlen(defaultfontname), defaultfontname); + if (err != Success) + return FALSE; + pf = (FontPtr) LookupIDByType(fid, RT_FONT); + if (pf == (FontPtr) NULL) + return FALSE; + defaultFont = pf; + return TRUE; +} + +/* + * note that the font wakeup queue is not refcounted. this is because + * an fpe needs to be added when it's inited, and removed when it's finally + * freed, in order to handle any data that isn't requested, like FS events. + * + * since the only thing that should call these routines is the renderer's + * init_fpe() and free_fpe(), there shouldn't be any problem in using + * freed data. + */ +void +QueueFontWakeup(FontPathElementPtr fpe) +{ + int i; + FontPathElementPtr *new; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + +#ifdef DEBUG + fprintf(stderr, "re-queueing fpe wakeup\n"); +#endif + + return; + } + } + if (num_slept_fpes == size_slept_fpes) { + new = (FontPathElementPtr *) + xrealloc(slept_fpes, + sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); + if (!new) + return; + slept_fpes = new; + size_slept_fpes += 4; + } + slept_fpes[num_slept_fpes] = fpe; + num_slept_fpes++; +} + +void +RemoveFontWakeup(FontPathElementPtr fpe) +{ + int i, + j; + + for (i = 0; i < num_slept_fpes; i++) { + if (slept_fpes[i] == fpe) { + for (j = i; j < num_slept_fpes; j++) { + slept_fpes[j] = slept_fpes[j + 1]; + } + num_slept_fpes--; + return; + } + } +} + +void +FontWakeup(pointer data, int count, pointer LastSelectMask) +{ + int i; + FontPathElementPtr fpe; + + if (count < 0) + return; + /* wake up any fpe's that may be waiting for information */ + for (i = 0; i < num_slept_fpes; i++) { + fpe = slept_fpes[i]; + (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); + } +} + +/* XXX -- these two funcs may want to be broken into macros */ +static void +UseFPE(FontPathElementPtr fpe) +{ + fpe->refcount++; +} + +static void +FreeFPE (FontPathElementPtr fpe) +{ + fpe->refcount--; + if (fpe->refcount == 0) { + (*fpe_functions[fpe->type].free_fpe) (fpe); + xfree(fpe->name); + xfree(fpe); + } +} + +static Bool +doOpenFont(ClientPtr client, OFclosurePtr c) +{ + FontPtr pfont = NullFont; + FontPathElementPtr fpe = NULL; + ScreenPtr pScr; + int err = Successful; + int i; + char *alias, + *newname; + int newlen; + int aliascount = 20; + /* + * Decide at runtime what FontFormat to use. + */ + Mask FontFormat = + + ((screenInfo.imageByteOrder == LSBFirst) ? + BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | + + ((screenInfo.bitmapBitOrder == LSBFirst) ? + BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | + + BitmapFormatImageRectMin | + +#if GLYPHPADBYTES == 1 + BitmapFormatScanlinePad8 | +#endif + +#if GLYPHPADBYTES == 2 + BitmapFormatScanlinePad16 | +#endif + +#if GLYPHPADBYTES == 4 + BitmapFormatScanlinePad32 | +#endif + +#if GLYPHPADBYTES == 8 + BitmapFormatScanlinePad64 | +#endif + + BitmapFormatScanlineUnit8; + + if (client->clientGone) + { + if (c->current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + while (c->current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current_fpe]; + err = (*fpe_functions[fpe->type].open_font) + ((pointer) client, fpe, c->flags, + c->fontname, c->fnamelen, FontFormat, + BitmapFormatMaskByte | + BitmapFormatMaskBit | + BitmapFormatMaskImageRectangle | + BitmapFormatMaskScanLinePad | + BitmapFormatMaskScanLineUnit, + c->fontid, &pfont, &alias, + c->non_cachable_font && c->non_cachable_font->fpe == fpe ? + c->non_cachable_font : + (FontPtr)0); + + if (err == FontNameAlias && alias) { + newlen = strlen(alias); + newname = (char *) xrealloc(c->fontname, newlen); + if (!newname) { + err = AllocError; + break; + } + memmove(newname, alias, newlen); + c->fontname = newname; + c->fnamelen = newlen; + c->current_fpe = 0; + if (--aliascount <= 0) + break; + continue; + } + if (err == BadFontName) { + c->current_fpe++; + continue; + } + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c); + } + return TRUE; + } + break; + } + + if (err != Successful) + goto bail; + if (!pfont) { + err = BadFontName; + goto bail; + } + if (!pfont->fpe) + pfont->fpe = fpe; + pfont->refcnt++; + if (pfont->refcnt == 1) { + UseFPE(pfont->fpe); + for (i = 0; i < screenInfo.numScreens; i++) { + pScr = screenInfo.screens[i]; + if (pScr->RealizeFont) + { + if (!(*pScr->RealizeFont) (pScr, pfont)) + { + CloseFont (pfont, (Font) 0); + err = AllocError; + goto bail; + } + } + } + } + if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { + err = AllocError; + goto bail; + } + if (patternCache && pfont != c->non_cachable_font) + CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, + pfont); +bail: + if (err != Successful && c->client != serverClient) { + SendErrorToClient(c->client, X_OpenFont, 0, + c->fontid, FontToXError(err)); + } + if (c->slept) + ClientWakeup(c->client); + for (i = 0; i < c->num_fpes; i++) { + FreeFPE(c->fpe_list[i]); + } + xfree(c->fpe_list); + xfree(c->fontname); + xfree(c); + return TRUE; +} + +int +OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) +{ + OFclosurePtr c; + int i; + FontPtr cached = (FontPtr)0; + +#ifdef FONTDEBUG + char *f; + f = (char *)xalloc(lenfname + 1); + memmove(f, pfontname, lenfname); + f[lenfname] = '\0'; + ErrorF("OpenFont: fontname is \"%s\"\n", f); + xfree(f); +#endif + if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) + return BadName; + if (patternCache) + { + + /* + ** Check name cache. If we find a cached version of this font that + ** is cachable, immediately satisfy the request with it. If we find + ** a cached version of this font that is non-cachable, we do not + ** satisfy the request with it. Instead, we pass the FontPtr to the + ** FPE's open_font code (the fontfile FPE in turn passes the + ** information to the rasterizer; the fserve FPE ignores it). + ** + ** Presumably, the font is marked non-cachable because the FPE has + ** put some licensing restrictions on it. If the FPE, using + ** whatever logic it relies on, determines that it is willing to + ** share this existing font with the client, then it has the option + ** to return the FontPtr we passed it as the newly-opened font. + ** This allows the FPE to exercise its licensing logic without + ** having to create another instance of a font that already exists. + */ + + cached = FindCachedFontPattern(patternCache, pfontname, lenfname); + if (cached && cached->info.cachable) + { + if (!AddResource(fid, RT_FONT, (pointer) cached)) + return BadAlloc; + cached->refcnt++; + return Success; + } + } + c = (OFclosurePtr) xalloc(sizeof(OFclosureRec)); + if (!c) + return BadAlloc; + c->fontname = (char *) xalloc(lenfname); + c->origFontName = pfontname; + c->origFontNameLen = lenfname; + if (!c->fontname) { + xfree(c); + return BadAlloc; + } + /* + * copy the current FPE list, so that if it gets changed by another client + * while we're blocking, the request still appears atomic + */ + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c->fontname); + xfree(c); + return BadAlloc; + } + memmove(c->fontname, pfontname, lenfname); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->fontid = fid; + c->current_fpe = 0; + c->num_fpes = num_fpes; + c->fnamelen = lenfname; + c->slept = FALSE; + c->flags = flags; + c->non_cachable_font = cached; + + (void) doOpenFont(client, c); + return Success; +} + +/** + * Decrement font's ref count, and free storage if ref count equals zero + * + * \param value must conform to DeleteType + */ +int +CloseFont(pointer value, XID fid) +{ + int nscr; + ScreenPtr pscr; + FontPathElementPtr fpe; + FontPtr pfont = (FontPtr)value; + + if (pfont == NullFont) + return (Success); + if (--pfont->refcnt == 0) { + if (patternCache) + RemoveCachedFontPattern (patternCache, pfont); + /* + * since the last reference is gone, ask each screen to free any + * storage it may have allocated locally for it. + */ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + if (pscr->UnrealizeFont) + (*pscr->UnrealizeFont) (pscr, pfont); + } + if (pfont == defaultFont) + defaultFont = NULL; +#ifdef LBX + LbxFreeFontTag(pfont); +#endif +#ifdef XF86BIGFONT + XF86BigfontFreeFontShm(pfont); +#endif + fpe = pfont->fpe; + (*fpe_functions[fpe->type].close_font) (fpe, pfont); + FreeFPE(fpe); + } + return (Success); +} + + +/***====================================================================***/ + +/** + * Sets up pReply as the correct QueryFontReply for pFont with the first + * nProtoCCIStructs char infos. + * + * \param pReply caller must allocate this storage + */ +void +QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) +{ + FontPropPtr pFP; + int r, + c, + i; + xFontProp *prFP; + xCharInfo *prCI; + xCharInfo *charInfos[256]; + unsigned char chars[512]; + int ninfos; + unsigned long ncols; + unsigned long count; + + /* pr->length set in dispatch */ + pReply->minCharOrByte2 = pFont->info.firstCol; + pReply->defaultChar = pFont->info.defaultCh; + pReply->maxCharOrByte2 = pFont->info.lastCol; + pReply->drawDirection = pFont->info.drawDirection; + pReply->allCharsExist = pFont->info.allExist; + pReply->minByte1 = pFont->info.firstRow; + pReply->maxByte1 = pFont->info.lastRow; + pReply->fontAscent = pFont->info.fontAscent; + pReply->fontDescent = pFont->info.fontDescent; + + pReply->minBounds = pFont->info.ink_minbounds; + pReply->maxBounds = pFont->info.ink_maxbounds; + + pReply->nFontProps = pFont->info.nprops; + pReply->nCharInfos = nProtoCCIStructs; + + for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); + i < pFont->info.nprops; + i++, pFP++, prFP++) { + prFP->name = pFP->name; + prFP->value = pFP->value; + } + + ninfos = 0; + ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); + prCI = (xCharInfo *) (prFP); + for (r = pFont->info.firstRow; + ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; + r++) { + i = 0; + for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { + chars[i++] = r; + chars[i++] = c; + } + (*pFont->get_metrics) (pFont, ncols, chars, + TwoD16Bit, &count, charInfos); + i = 0; + for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { + *prCI = *charInfos[i]; + prCI++; + ninfos++; + } + } + return; +} + +static Bool +doListFontsAndAliases(ClientPtr client, LFclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + FontNamesPtr names = NULL; + char *name, *resolved=NULL; + int namelen, resolvedlen; + int nnames; + int stringLens; + int i; + xListFontsReply reply; + char *bufptr; + char *bufferStart; + int aliascount = 0; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + + if (!c->current.patlen) + goto finish; + + while (c->current.current_fpe < c->num_fpes) { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + + if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) + { + /* This FPE doesn't support/require list_fonts_and_aliases */ + + err = (*fpe_functions[fpe->type].list_fonts) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + c->names); + + if (err == Suspended) { + if (!c->slept) { + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + } + return TRUE; + } + + err = BadFontName; + } + else + { + /* Start of list_fonts_and_aliases functionality. Modeled + after list_fonts_with_info in that it resolves aliases, + except that the information collected from FPEs is just + names, not font info. Each list_next_font_or_alias() + returns either a name into name/namelen or an alias into + name/namelen and its target name into resolved/resolvedlen. + The code at this level then resolves the alias by polling + the FPEs. */ + + if (!c->current.list_started) { + err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) + ((pointer) c->client, fpe, c->current.pattern, + c->current.patlen, c->current.max_names - c->names->nnames, + &c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) { + char *tmpname; + name = 0; + err = (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &name, &namelen, &tmpname, + &resolvedlen, c->current.private); + if (err == Suspended) { + if (!c->slept) { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsAndAliases, + (pointer) c); + c->slept = TRUE; + } + return TRUE; + } + if (err == FontNameAlias) { + if (resolved) xfree(resolved); + resolved = (char *) xalloc(resolvedlen + 1); + if (resolved) + memmove(resolved, tmpname, resolvedlen + 1); + } + } + + if (err == Successful) + { + if (c->haveSaved) + { + if (c->savedName) + (void)AddFontNamesName(c->names, c->savedName, + c->savedNameLen); + } + else + (void)AddFontNamesName(c->names, name, namelen); + } + + /* + * When we get an alias back, save our state and reset back to + * the start of the FPE looking for the specified name. As + * soon as a real font is found for the alias, pop back to the + * old state + */ + else if (err == FontNameAlias) { + char tmp_pattern[XLFDMAXFONTNAMELEN]; + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + memmove(tmp_pattern, resolved, resolvedlen); + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + + tmpname = 0; + (void) (*fpe_functions[fpe->type].list_next_font_or_alias) + ((pointer) c->client, fpe, &tmpname, &tmpnamelen, + &tmpname, &tmpnamelen, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + c->savedNameLen = namelen; + aliascount = 20; + } + memmove(c->current.pattern, tmp_pattern, resolvedlen); + c->current.patlen = resolvedlen; + c->current.max_names = c->names->nnames + 1; + c->current.current_fpe = -1; + c->current.private = 0; + err = BadFontName; + } + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've collected enough + * font names, quit. + */ + if (err == BadFontName) { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->names->nnames == c->current.max_names || + c->current.current_fpe == c->num_fpes) { + c->haveSaved = FALSE; + c->current = c->saved; + /* Give the saved namelist a chance to clean itself up */ + continue; + } + } + if (c->names->nnames == c->current.max_names) + break; + } + } + + /* + * send the reply + */ + if (err != Successful) { + SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); + goto bail; + } + +finish: + + names = c->names; + nnames = names->nnames; + client = c->client; + stringLens = 0; + for (i = 0; i < nnames; i++) + stringLens += (names->length[i] <= 255) ? names->length[i] : 0; + + reply.type = X_Reply; + reply.length = (stringLens + nnames + 3) >> 2; + reply.nFonts = nnames; + reply.sequenceNumber = client->sequence; + + bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); + + if (!bufptr && reply.length) { + SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); + goto bail; + } + /* + * since WriteToClient long word aligns things, copy to temp buffer and + * write all at once + */ + for (i = 0; i < nnames; i++) { + if (names->length[i] > 255) + reply.nFonts--; + else + { + *bufptr++ = names->length[i]; + memmove( bufptr, names->names[i], names->length[i]); + bufptr += names->length[i]; + } + } + nnames = reply.nFonts; + reply.length = (stringLens + nnames + 3) >> 2; + client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; + WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); + (void) WriteToClient(client, stringLens + nnames, bufferStart); + DEALLOCATE_LOCAL(bufferStart); + +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + FreeFontNames(names); + xfree(c); + if (resolved) xfree(resolved); + return TRUE; +} + +int +ListFonts(ClientPtr client, unsigned char *pattern, unsigned length, + unsigned max_names) +{ + int i; + LFclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFclosurePtr) xalloc(sizeof *c))) + return BadAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) { + xfree(c); + return BadAlloc; + } + c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); + if (!c->names) + { + xfree(c->fpe_list); + xfree(c); + return BadAlloc; + } + memmove( c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsAndAliases(client, c); + return Success; +} + +int +doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) +{ + FontPathElementPtr fpe; + int err = Successful; + char *name; + int namelen; + int numFonts; + FontInfoRec fontInfo, + *pFontInfo; + xListFontsWithInfoReply *reply; + int length; + xFontProp *pFP; + int i; + int aliascount = 0; + xListFontsWithInfoReply finalReply; + + if (client->clientGone) + { + if (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } + err = Successful; + goto bail; + } + client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; + if (!c->current.patlen) + goto finish; + while (c->current.current_fpe < c->num_fpes) + { + fpe = c->fpe_list[c->current.current_fpe]; + err = Successful; + if (!c->current.list_started) + { + err = (*fpe_functions[fpe->type].start_list_fonts_with_info) + (client, fpe, c->current.pattern, c->current.patlen, + c->current.max_names, &c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c); + c->slept = TRUE; + } + return TRUE; + } + if (err == Successful) + c->current.list_started = TRUE; + } + if (err == Successful) + { + name = 0; + pFontInfo = &fontInfo; + err = (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &name, &namelen, &pFontInfo, + &numFonts, c->current.private); + if (err == Suspended) + { + if (!c->slept) + { + ClientSleep(client, + (ClientSleepProcPtr)doListFontsWithInfo, + c); + c->slept = TRUE; + } + return TRUE; + } + } + /* + * When we get an alias back, save our state and reset back to the + * start of the FPE looking for the specified name. As soon as a real + * font is found for the alias, pop back to the old state + */ + if (err == FontNameAlias) + { + /* + * when an alias recurses, we need to give + * the last FPE a chance to clean up; so we call + * it again, and assume that the error returned + * is BadFontName, indicating the alias resolution + * is complete. + */ + if (c->haveSaved) + { + char *tmpname; + int tmpnamelen; + FontInfoPtr tmpFontInfo; + + tmpname = 0; + tmpFontInfo = &fontInfo; + (void) (*fpe_functions[fpe->type].list_next_font_with_info) + (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, + &numFonts, c->current.private); + if (--aliascount <= 0) + { + err = BadFontName; + goto ContBadFontName; + } + } + else + { + c->saved = c->current; + c->haveSaved = TRUE; + c->savedNumFonts = numFonts; + if (c->savedName) + xfree(c->savedName); + c->savedName = (char *)xalloc(namelen + 1); + if (c->savedName) + memmove(c->savedName, name, namelen + 1); + aliascount = 20; + } + memmove(c->current.pattern, name, namelen); + c->current.patlen = namelen; + c->current.max_names = 1; + c->current.current_fpe = 0; + c->current.private = 0; + c->current.list_started = FALSE; + } + /* + * At the end of this FPE, step to the next. If we've finished + * processing an alias, pop state back. If we've sent enough font + * names, quit. Always wait for BadFontName to let the FPE + * have a chance to clean up. + */ + else if (err == BadFontName) + { + ContBadFontName: ; + c->current.list_started = FALSE; + c->current.current_fpe++; + err = Successful; + if (c->haveSaved) + { + if (c->current.max_names == 0 || + c->current.current_fpe == c->num_fpes) + { + c->haveSaved = FALSE; + c->saved.max_names -= (1 - c->current.max_names); + c->current = c->saved; + } + } + else if (c->current.max_names == 0) + break; + } + else if (err == Successful) + { + length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); + reply = c->reply; + if (c->length < length) + { + reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length); + if (!reply) + { + err = AllocError; + break; + } + c->reply = reply; + c->length = length; + } + if (c->haveSaved) + { + numFonts = c->savedNumFonts; + name = c->savedName; + namelen = strlen(name); + } + reply->type = X_Reply; + reply->length = (sizeof *reply - sizeof(xGenericReply) + + pFontInfo->nprops * sizeof(xFontProp) + + namelen + 3) >> 2; + reply->sequenceNumber = client->sequence; + reply->nameLength = namelen; + reply->minBounds = pFontInfo->ink_minbounds; + reply->maxBounds = pFontInfo->ink_maxbounds; + reply->minCharOrByte2 = pFontInfo->firstCol; + reply->maxCharOrByte2 = pFontInfo->lastCol; + reply->defaultChar = pFontInfo->defaultCh; + reply->nFontProps = pFontInfo->nprops; + reply->drawDirection = pFontInfo->drawDirection; + reply->minByte1 = pFontInfo->firstRow; + reply->maxByte1 = pFontInfo->lastRow; + reply->allCharsExist = pFontInfo->allExist; + reply->fontAscent = pFontInfo->fontAscent; + reply->fontDescent = pFontInfo->fontDescent; + reply->nReplies = numFonts; + pFP = (xFontProp *) (reply + 1); + for (i = 0; i < pFontInfo->nprops; i++) + { + pFP->name = pFontInfo->props[i].name; + pFP->value = pFontInfo->props[i].value; + pFP++; + } + WriteSwappedDataToClient(client, length, reply); + (void) WriteToClient(client, namelen, name); + if (pFontInfo == &fontInfo) + { + xfree(fontInfo.props); + xfree(fontInfo.isStringProp); + } + --c->current.max_names; + } + } +finish: + length = sizeof(xListFontsWithInfoReply); + bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply)); + finalReply.type = X_Reply; + finalReply.sequenceNumber = client->sequence; + finalReply.length = (sizeof(xListFontsWithInfoReply) + - sizeof(xGenericReply)) >> 2; + WriteSwappedDataToClient(client, length, &finalReply); +bail: + if (c->slept) + ClientWakeup(client); + for (i = 0; i < c->num_fpes; i++) + FreeFPE(c->fpe_list[i]); + xfree(c->reply); + xfree(c->fpe_list); + if (c->savedName) xfree(c->savedName); + xfree(c); + return TRUE; +} + +int +StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, + int max_names) +{ + int i; + LFWIclosurePtr c; + + /* + * The right error to return here would be BadName, however the + * specification does not allow for a Name error on this request. + * Perhaps a better solution would be to return a nil list, i.e. + * a list containing zero fontnames. + */ + if (length > XLFDMAXFONTNAMELEN) + return BadAlloc; + + if (!(c = (LFWIclosurePtr) xalloc(sizeof *c))) + goto badAlloc; + c->fpe_list = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * num_fpes); + if (!c->fpe_list) + { + xfree(c); + goto badAlloc; + } + memmove(c->current.pattern, pattern, length); + for (i = 0; i < num_fpes; i++) + { + c->fpe_list[i] = font_path_elements[i]; + UseFPE(c->fpe_list[i]); + } + c->client = client; + c->num_fpes = num_fpes; + c->reply = 0; + c->length = 0; + c->current.patlen = length; + c->current.current_fpe = 0; + c->current.max_names = max_names; + c->current.list_started = FALSE; + c->current.private = 0; + c->savedNumFonts = 0; + c->haveSaved = FALSE; + c->slept = FALSE; + c->savedName = 0; + doListFontsWithInfo(client, c); + return Success; +badAlloc: + return BadAlloc; +} + +#define TextEltHeader 2 +#define FontShiftSize 5 +static XID clearGC[] = { CT_NONE }; +#define clearGCmask (GCClipMask) + +int +doPolyText(ClientPtr client, register PTclosurePtr c) +{ + register FontPtr pFont = c->pGC->font, oldpFont; + Font fid, oldfid; + int err = Success, lgerr; /* err is in X error, not font error, space */ + enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; + FontPathElementPtr fpe; + GC *origGC = NULL; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + + if (c->slept) + { + /* Client has died, but we cannot bail out right now. We + need to clean up after the work we did when going to + sleep. Setting the drawable pointer to 0 makes this + happen without any attempts to render or perform other + unnecessary activities. */ + c->pDraw = (DrawablePtr)0; + } + else + { + err = Success; + goto bail; + } + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client and avoid further + rendering while we clean up after ourself. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + c->pDraw = (DrawablePtr)0; + } + + client_state = c->slept ? SLEEPING : NEVER_SLEPT; + + while (c->endReq - c->pElt > TextEltHeader) + { + if (*c->pElt == FontChange) + { + if (c->endReq - c->pElt < FontShiftSize) + { + err = BadLength; + goto bail; + } + + oldpFont = pFont; + oldfid = fid; + + fid = ((Font)*(c->pElt+4)) /* big-endian */ + | ((Font)*(c->pElt+3)) << 8 + | ((Font)*(c->pElt+2)) << 16 + | ((Font)*(c->pElt+1)) << 24; + pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT, + SecurityReadAccess); + if (!pFont) + { + client->errorValue = fid; + err = BadFont; + /* restore pFont and fid for step 4 (described below) */ + pFont = oldpFont; + fid = oldfid; + + /* If we're in START_SLEEP mode, the following step + shortens the request... in the unlikely event that + the fid somehow becomes valid before we come through + again to actually execute the polytext, which would + then mess up our refcounting scheme badly. */ + c->err = err; + c->endReq = c->pElt; + + goto bail; + } + + /* Step 3 (described below) on our new font */ + if (client_state == START_SLEEP) + pFont->refcnt++; + else + { + if (pFont != c->pGC->font && c->pDraw) + { + ChangeGC( c->pGC, GCFont, &fid); + ValidateGC(c->pDraw, c->pGC); + if (c->reqType == X_PolyText8) + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; + else + c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; + } + + /* Undo the refcnt++ we performed when going to sleep */ + if (client_state == SLEEPING) + (void)CloseFont(c->pGC->font, (Font)0); + } + c->pElt += FontShiftSize; + } + else /* print a string */ + { + unsigned char *pNextElt; + pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; + if ( pNextElt > c->endReq) + { + err = BadLength; + goto bail; + } + if (client_state == START_SLEEP) + { + c->pElt = pNextElt; + continue; + } + if (c->pDraw) + { + lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, + c->pElt + TextEltHeader); + } + else lgerr = Successful; + + if (lgerr == Suspended) + { + if (!c->slept) { + int len; + GC *pGC; + PTclosurePtr new_closure; + + /* We're putting the client to sleep. We need to do a few things + to ensure successful and atomic-appearing execution of the + remainder of the request. First, copy the remainder of the + request into a safe malloc'd area. Second, create a scratch GC + to use for the remainder of the request. Third, mark all fonts + referenced in the remainder of the request to prevent their + deallocation. Fourth, make the original GC look like the + request has completed... set its font to the final font value + from this request. These GC manipulations are for the unlikely + (but possible) event that some other client is using the GC. + Steps 3 and 4 are performed by running this procedure through + the remainder of the request in a special no-render mode + indicated by client_state = START_SLEEP. */ + + /* Step 1 */ + /* Allocate a malloc'd closure structure to replace + the local one we were passed */ + new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + len = c->endReq - c->pElt; + c->data = (unsigned char *)xalloc(len); + if (!c->data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(c->data, c->pElt, len); + c->pElt = c->data; + c->endReq = c->pElt + len; + + /* Step 2 */ + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | + GCPlaneMask | GCForeground | + GCBackground | GCFillStyle | + GCTile | GCStipple | + GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != + Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + origGC = c->pGC; + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, + (ClientSleepProcPtr)doPolyText, + (pointer) c); + + /* Set up to perform steps 3 and 4 */ + client_state = START_SLEEP; + continue; /* on to steps 3 and 4 */ + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ + c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, + *c->pElt, c->pElt + TextEltHeader); + } + c->pElt = pNextElt; + } + } + +bail: + + if (client_state == START_SLEEP) + { + /* Step 4 */ + if (pFont != origGC->font) + { + ChangeGC(origGC, GCFont, &fid); + ValidateGC(c->pDraw, origGC); + } + + /* restore pElt pointer for execution of remainder of the request */ + c->pElt = c->data; + return TRUE; + } + + if (c->err != Success) err = c->err; + if (err != Success && c->client != serverClient) { +#ifdef PANORAMIX + if (noPanoramiXExtension || !c->pGC->pScreen->myNum) +#endif + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, + unsigned char *endReq, int xorg, int yorg, int reqType, XID did) +{ + PTclosureRec local_closure; + + local_closure.pElt = pElt; + local_closure.endReq = endReq; + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_PolyText8) + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; + local_closure.itemSize = 1; + } + else + { + local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; + local_closure.itemSize = 2; + } + local_closure.pGC = pGC; + local_closure.did = did; + local_closure.err = Success; + local_closure.slept = FALSE; + + (void) doPolyText(client, &local_closure); + return Success; +} + + +#undef TextEltHeader +#undef FontShiftSize + +int +doImageText(ClientPtr client, register ITclosurePtr c) +{ + int err = Success, lgerr; /* err is in X error, not font error, space */ + FontPathElementPtr fpe; + + if (client->clientGone) + { + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + /* Make sure our drawable hasn't disappeared while we slept. */ + if (c->slept && + c->pDraw && + c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did, + RC_DRAWABLE, SecurityWriteAccess)) + { + /* Our drawable has disappeared. Treat like client died... ask + the FPE code to clean up after client. */ + fpe = c->pGC->font->fpe; + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + err = Success; + goto bail; + } + + lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); + if (lgerr == Suspended) + { + if (!c->slept) { + GC *pGC; + unsigned char *data; + ITclosurePtr new_closure; + + /* We're putting the client to sleep. We need to + save some state. Similar problem to that handled + in doPolyText, but much simpler because the + request structure is much simpler. */ + + new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec)); + if (!new_closure) + { + err = BadAlloc; + goto bail; + } + *new_closure = *c; + c = new_closure; + + data = (unsigned char *)xalloc(c->nChars * c->itemSize); + if (!data) + { + xfree(c); + err = BadAlloc; + goto bail; + } + memmove(data, c->data, c->nChars * c->itemSize); + c->data = data; + + pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); + if (!pGC) + { + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | + GCForeground | GCBackground | GCFillStyle | + GCTile | GCStipple | GCTileStipXOrigin | + GCTileStipYOrigin | GCFont | + GCSubwindowMode | GCClipXOrigin | + GCClipYOrigin | GCClipMask)) != Success) + { + FreeScratchGC(pGC); + xfree(c->data); + xfree(c); + err = BadAlloc; + goto bail; + } + c->pGC = pGC; + ValidateGC(c->pDraw, c->pGC); + + c->slept = TRUE; + ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c); + } + return TRUE; + } + else if (lgerr != Successful) + { + err = FontToXError(lgerr); + goto bail; + } + if (c->pDraw) + { + (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, + c->nChars, c->data); + } + +bail: + + if (err != Success && c->client != serverClient) { + SendErrorToClient(c->client, c->reqType, 0, 0, err); + } + if (c->slept) + { + ClientWakeup(c->client); + ChangeGC(c->pGC, clearGCmask, clearGC); + + /* Unreference the font from the scratch GC */ + CloseFont(c->pGC->font, (Font)0); + c->pGC->font = NullFont; + + FreeScratchGC(c->pGC); + xfree(c->data); + xfree(c); + } + return TRUE; +} + +int +ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, + unsigned char *data, int xorg, int yorg, int reqType, XID did) +{ + ITclosureRec local_closure; + + local_closure.client = client; + local_closure.pDraw = pDraw; + local_closure.pGC = pGC; + local_closure.nChars = nChars; + local_closure.data = data; + local_closure.xorg = xorg; + local_closure.yorg = yorg; + if ((local_closure.reqType = reqType) == X_ImageText8) + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; + local_closure.itemSize = 1; + } + else + { + local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; + local_closure.itemSize = 2; + } + local_closure.did = did; + local_closure.slept = FALSE; + + (void) doImageText(client, &local_closure); + return Success; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +DetermineFPEType(char *pathname) +{ + int i; + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static void +FreeFontPath(FontPathElementPtr *list, int n, Bool force) +{ + int i; + + for (i = 0; i < n; i++) { + if (force) { + /* Sanity check that all refcounts will be 0 by the time + we get to the end of the list. */ + int found = 1; /* the first reference is us */ + int j; + for (j = i+1; j < n; j++) { + if (list[j] == list[i]) + found++; + } + if (list[i]->refcount != found) { + ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n", + list[i]->name_length, list[i]->name, + list[i]->refcount, found); + list[i]->refcount = found; /* ensure it will get freed */ + } + } + FreeFPE(list[i]); + } + xfree((char *) list); +} + +static FontPathElementPtr +find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) +{ + FontPathElementPtr fpe; + int i; + + for (i = 0; i < num; i++) { + fpe = list[i]; + if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) + return fpe; + } + return (FontPathElementPtr) 0; +} + + +static int +SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) +{ + int i, err = 0; + int valid_paths = 0; + unsigned int len; + unsigned char *cp = paths; + FontPathElementPtr fpe = NULL, *fplist; + + fplist = (FontPathElementPtr *) + xalloc(sizeof(FontPathElementPtr) * npaths); + if (!fplist) { + *bad = 0; + return BadAlloc; + } + for (i = 0; i < num_fpe_types; i++) { + if (fpe_functions[i].set_path_hook) + (*fpe_functions[i].set_path_hook) (); + } + for (i = 0; i < npaths; i++) + { + len = (unsigned int) (*cp++); + + if (len == 0) + { + if (persist) + ErrorF ("Removing empty element from the valid list of fontpaths\n"); + err = BadValue; + } + else + { + /* if it's already in our active list, just reset it */ + /* + * note that this can miss FPE's in limbo -- may be worth catching + * them, though it'd muck up refcounting + */ + fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); + if (fpe) + { + err = (*fpe_functions[fpe->type].reset_fpe) (fpe); + if (err == Successful) + { + UseFPE(fpe);/* since it'll be decref'd later when freed + * from the old list */ + } + else + fpe = 0; + } + /* if error or can't do it, act like it's a new one */ + if (!fpe) + { + fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec)); + if (!fpe) + { + err = BadAlloc; + goto bail; + } + fpe->name = (char *) xalloc(len + 1); + if (!fpe->name) + { + xfree(fpe); + err = BadAlloc; + goto bail; + } + fpe->refcount = 1; + + strncpy(fpe->name, (char *) cp, (int) len); + fpe->name[len] = '\0'; + fpe->name_length = len; + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err = BadValue; + else + err = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (err != Successful) + { + if (persist) + { + ErrorF("Could not init font path element %s, removing from list!\n", + fpe->name); + } + xfree (fpe->name); + xfree (fpe); + } + } + } + if (err != Successful) + { + if (!persist) + goto bail; + } + else + { + fplist[valid_paths++] = fpe; + } + cp += len; + } + + FreeFontPath(font_path_elements, num_fpes, FALSE); + font_path_elements = fplist; + if (patternCache) + EmptyFontPatternCache(patternCache); + num_fpes = valid_paths; + + return Success; +bail: + *bad = i; + while (--valid_paths >= 0) + FreeFPE(fplist[valid_paths]); + xfree(fplist); + return FontToXError(err); +} + +/* XXX -- do we need to pass error down to each renderer? */ +int +SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error) +{ + int err = Success; + + if (npaths == 0) { + if (SetDefaultFontPath(defaultFontPath) != Success) + return BadValue; + } else { + err = SetFontPathElements(npaths, paths, error, FALSE); + } + return err; +} + +int +SetDefaultFontPath(char *path) +{ + unsigned char *cp, + *pp, + *nump, + *newpath; + int num = 1, + len, + err, + size = 0, + bad; + + /* get enough for string, plus values -- use up commas */ + len = strlen(path) + 1; + nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len); + if (!newpath) + return BadAlloc; + pp = (unsigned char *) path; + cp++; + while (*pp) { + if (*pp == ',') { + *nump = (unsigned char) size; + nump = cp++; + pp++; + num++; + size = 0; + } else { + *cp++ = *pp++; + size++; + } + } + *nump = (unsigned char) size; + + err = SetFontPathElements(num, newpath, &bad, TRUE); + + DEALLOCATE_LOCAL(newpath); + + return err; +} + +unsigned char * +GetFontPath(int *count, int *length) +{ + int i; + unsigned char *c; + int len; + FontPathElementPtr fpe; + + len = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + len += fpe->name_length + 1; + } + font_path_string = (unsigned char *) xrealloc(font_path_string, len); + if (!font_path_string) + return NULL; + + c = font_path_string; + *length = 0; + for (i = 0; i < num_fpes; i++) { + fpe = font_path_elements[i]; + *c = fpe->name_length; + *length += *c++; + memmove(c, fpe->name, fpe->name_length); + c += fpe->name_length; + } + *count = num_fpes; + return font_path_string; +} + +int +LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, unsigned char *data) +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} + +void +DeleteClientFontStuff(ClientPtr client) +{ + int i; + FontPathElementPtr fpe; + + for (i = 0; i < num_fpes; i++) + { + fpe = font_path_elements[i]; + if (fpe_functions[fpe->type].client_died) + (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); + } +} + +void +InitFonts () +{ + patternCache = MakeFontPatternCache(); + +#ifndef KDRIVESERVER + if (screenInfo.numScreens > screenInfo.numVideoScreens) { + PrinterFontRegisterFpeFunctions(); + FontFileCheckRegisterFpeFunctions(); + check_fs_register_fpe_functions(); + } else +#endif + { +#ifdef KDRIVESERVER + BuiltinRegisterFpeFunctions(); +#endif + FontFileRegisterFpeFunctions(); +#ifndef NOFONTSERVERACCESS + fs_register_fpe_functions(); +#endif + } +} + +int +GetDefaultPointSize () +{ + return 120; +} + + +FontResolutionPtr +GetClientResolutions (int *num) +{ + if (requestingClient && requestingClient->fontResFunc != NULL && + !requestingClient->clientGone) + { + return (*requestingClient->fontResFunc)(requestingClient, num); + } + else { + static struct _FontResolution res; + ScreenPtr pScreen; + + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; + } +} + +/* + * returns the type index of the new fpe + * + * should be called (only once!) by each type of fpe when initialized + */ + +int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = (FPEFunctions *) xrealloc(fpe_functions, + (num_fpe_types + 1) * sizeof(FPEFunctions)); + if (!new) + return -1; + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = + start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = + next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = + next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +void +FreeFonts() +{ + if (patternCache) { + FreeFontPatternCache(patternCache); + patternCache = 0; + } + FreeFontPath(font_path_elements, num_fpes, TRUE); + font_path_elements = 0; + num_fpes = 0; + xfree(fpe_functions); + num_fpe_types = 0; + fpe_functions = (FPEFunctions *) 0; +} + +/* convenience functions for FS interface */ + +FontPtr +find_old_font(XID id) +{ + return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE, + SecurityUnknownAccess); +} + +Font +GetNewFontClientID() +{ + return FakeClientID(0); +} + +int +StoreFontClientFont(FontPtr pfont, Font id) +{ + return AddResource(id, RT_NONE, (pointer) pfont); +} + +void +DeleteFontClientID(Font id) +{ + FreeResource(id, RT_NONE); +} + +int +client_auth_generation(ClientPtr client) +{ + return 0; +} + +static int fs_handlers_installed = 0; +static unsigned int last_server_gen; + +int +init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) +{ + /* if server has reset, make sure the b&w handlers are reinstalled */ + if (last_server_gen < serverGeneration) { + last_server_gen = serverGeneration; + fs_handlers_installed = 0; + } + if (fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "adding FS b & w handlers\n"); +#endif + + if (!RegisterBlockAndWakeupHandlers(block_handler, + FontWakeup, (pointer) 0)) + return AllocError; + fs_handlers_installed++; + } + QueueFontWakeup(fpe); + return Successful; +} + +void +remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) +{ + if (all) { + /* remove the handlers if no one else is using them */ + if (--fs_handlers_installed == 0) { + +#ifdef DEBUG + fprintf(stderr, "removing FS b & w handlers\n"); +#endif + + RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, + (pointer) 0); + } + } + RemoveFontWakeup(fpe); +} + +#ifdef DEBUG +#define GLWIDTHBYTESPADDED(bits,nbytes) \ + ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \ + :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \ + :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \ + :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \ + : 0) + +#define GLYPH_SIZE(ch, nbytes) \ + GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \ + (ch)->metrics.leftSideBearing, (nbytes)) +void +dump_char_ascii(CharInfoPtr cip) +{ + int r, + l; + int bpr; + int byte; + static unsigned maskTab[] = { + (1 << 7), (1 << 6), (1 << 5), (1 << 4), + (1 << 3), (1 << 2), (1 << 1), (1 << 0), + }; + + bpr = GLYPH_SIZE(cip, 4); + for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) { + pointer row = (pointer) cip->bits + r * bpr; + + byte = 0; + for (l = 0; l <= (cip->metrics.rightSideBearing - + cip->metrics.leftSideBearing); l++) { + if (maskTab[l & 7] & row[l >> 3]) + putchar('X'); + else + putchar('.'); + } + putchar('\n'); + } +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c new file mode 100644 index 000000000..91e290996 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c @@ -0,0 +1,4827 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.17 2005/08/25 22:11:04 anholt Exp $ */ +/* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/***************************************************************** + +Copyright 2003-2005 Sun Microsystems, 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, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +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 +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +******************************************************************/ + +/* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "Xlib.h" +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "globals.h" + +#ifdef XKB +#include +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +#endif + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif + +#ifdef XEVIE +extern WindowPtr *WindowTable; +extern int xevieFlag; +extern int xevieClientIndex; +extern DeviceIntPtr xeviemouse; +extern DeviceIntPtr xeviekb; +extern Mask xevieMask; +extern Mask xevieFilters[128]; +extern int xevieEventSent; +extern int xevieKBEventSent; +int xeviegrabState = 0; +xEvent *xeviexE; +#endif + +#include +#include "exevents.h" +#include "extnsionst.h" + +#include "dixevents.h" +#include "dixgrabs.h" +#include "../../dix/dispatch.h" + +#include "NXlib.h" + +#include "Events.h" +#include "Windows.h" +#include "Args.h" + +extern Display *nxagentDisplay; + +extern WindowPtr nxagentLastEnteredWindow; + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the ButtonMotionMasks are equal + * to the corresponding ButtonMasks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define XE_KBPTR (xE->u.keyButtonPointer) + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +CallbackListPtr EventCallback; +CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif +} sprite; /* info about the cursor sprite */ + +#ifdef XEVIE +WindowPtr xeviewin; +HotSpot xeviehot; +#endif + +static void DoEnterLeaveEvents( + WindowPtr fromWin, + WindowPtr toWin, + int mode +); + +static WindowPtr XYToWindow( + int x, + int y +); + +extern int lastEvent; + +static Mask lastEventMask; + +#ifdef XINPUT +extern int DeviceMotionNotify; +#endif + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x7c /* key and button events */ +}; + +#ifdef PANORAMIX + +static void ConfineToShape(RegionPtr shape, int *px, int *py); +static void SyntheticMotion(int x, int y); +static void PostNewCursor(void); + +static Bool +XineramaSetCursorPosition( + int x, + int y, + Bool generateEvent +){ + ScreenPtr pScreen; + BoxRec box; + int i; + + /* x,y are in Screen 0 coordinates. We need to decide what Screen + to send the message too and what the coordinates relative to + that screen are. */ + + pScreen = sprite.screen; + x += panoramiXdataPtr[0].x; + y += panoramiXdataPtr[0].y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) + { + FOR_NSCREENS(i) + { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) + { + pScreen = screenInfo.screens[i]; + break; + } + } + } + + sprite.screen = pScreen; + sprite.hotPhys.x = x - panoramiXdataPtr[0].x; + sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + x -= panoramiXdataPtr[pScreen->myNum].x; + y -= panoramiXdataPtr[pScreen->myNum].y; + + return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); +} + + +static void +XineramaConstrainCursor(void) +{ + ScreenPtr pScreen = sprite.screen; + BoxRec newBox = sprite.physLimits; + + /* Translate the constraining box to the screen + the sprite is actually on */ + newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + + (* pScreen->ConstrainCursor)(pScreen, &newBox); +} + +static void +XineramaCheckPhysLimits( + CursorPtr cursor, + Bool generateEvents +){ + HotSpot new; + + if (!cursor) + return; + + new = sprite.hotPhys; + + /* I don't care what the DDX has to say about it */ + sprite.physLimits = sprite.hotLimits; + + /* constrain the pointer to those limits */ + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) /* more work if the shape is a mess */ + ConfineToShape(sprite.hotShape, &new.x, &new.y); + + if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + XineramaSetCursorPosition (new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } + + /* Tell DDX what the limits are */ + XineramaConstrainCursor(); +} + + +static Bool +XineramaSetWindowPntrs(WindowPtr pWin) +{ + if(pWin == WindowTable[0]) { + memcpy(sprite.windows, WindowTable, + PanoramiXNumScreens*sizeof(WindowPtr)); + } else { + PanoramiXRes *win; + int i; + + win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); + + if(!win) + return FALSE; + + for(i = 0; i < PanoramiXNumScreens; i++) { + sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!sprite.windows[i]) /* window is being unmapped */ + return FALSE; + } + } + return TRUE; +} + +static void +XineramaCheckVirtualMotion( + QdEventPtr qe, + WindowPtr pWin +){ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + int x, y, off_x, off_y, i; + BoxRec lims; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg2, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + + if (sprite.hot.x < lims.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y2 - 1; + + if (REGION_NUM_RECTS(&sprite.Reg2) > 1) + ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +} + + +static Bool +XineramaCheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + /* Motion events entering DIX get translated to Screen 0 + coordinates. Replayed events have already been + translated since they've entered DIX before */ + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = XE_KBPTR.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + XineramaSetCursorPosition( + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + + +static void +XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +{ + + if (syncEvents.playingEvents) + { + XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + int x, y, off_x, off_y, i; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg1, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + + if(REGION_NUM_RECTS(&sprite.Reg1) > 1) + sprite.hotShape = &sprite.Reg1; + else + sprite.hotShape = NullRegion; + + sprite.confined = FALSE; + sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + + XineramaCheckPhysLimits(sprite.current, generateEvents); + } +} + + +static void +XineramaChangeToCursor(CursorPtr cursor) +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(cursor, FALSE); + (*sprite.screen->DisplayCursor)(sprite.screen, cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + + +#endif /* PANORAMIX */ + +void +SetMaskForEvent(Mask mask, int event) +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +void +SetCriticalEvent(int event) +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +SyntheticMotion(int x, int y) +{ + xEvent xE; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x; + y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +ConfineToShape(RegionPtr shape, int *px, int *py) +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +CheckPhysLimits( + CursorPtr cursor, + Bool generateEvents, + Bool confineToScreen, + ScreenPtr pScreen) +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +CheckVirtualMotion( + register QdEventPtr qe, + register WindowPtr pWin) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaCheckVirtualMotion(qe, pWin); + return; + } +#endif + if (qe) + { + sprite.hot.pScreen = qe->pScreen; +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; +#ifdef XEVIE + xeviehot.x = xeviehot.y = 0; +#endif + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaConfineCursorToWindow(pWin, generateEvents); + return; + } +#endif + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +ChangeToCursor(CursorPtr cursor) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaChangeToCursor(cursor); + return; + } +#endif + + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, sprite.confined, + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(register WindowPtr a, register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +PostNewCursor(void) +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +void +GetSpritePosition(int *px, int *py) +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#ifdef PANORAMIX +int +XineramaGetCursorScreen() +{ + if(!noPanoramiXExtension) { + return sprite.screen->myNum; + } else { + return 0; + } +} +#endif /* PANORAMIX */ + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +MonthChangedOrBadTime(register xEvent *xE) +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) + currentTime.months++; + else + XE_KBPTR.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(register xEvent *xE) +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + +#ifdef XKB + /* Fix for key repeating bug. */ + if (device->key != NULL && device->key->xkbInfo != NULL && + xE->u.u.type == KeyRelease) + AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); +#endif + + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + } +#endif + sprite.hotPhys.x = XE_KBPTR.rootX; + sprite.hotPhys.y = XE_KBPTR.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = XE_KBPTR.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +PlayReleasedEvents(void) +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +FreezeThaw(register DeviceIntPtr dev, Bool frozen) +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + + w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < spriteTraceGood; i++) + { + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + } + goto playmore; + } + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +#ifdef RANDR +void +ScreenRestructured (ScreenPtr pScreen) +{ + GrabPtr grab; + + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab, + TimeStamp time, Bool autoGrab) +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + + #ifdef NXAGENT_SERVER + + /* + * If grab is synchronous, events are delivered to clients only if they send + * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the + * delivered event is saved in a queue and replayed later, when grab is released. + * We should export sync grab to X as async in order to avoid events to be + * queued twice, in the agent and in the X server. This solution have a drawback: + * replayed events are not delivered to that application that are not clients of + * the agent. + * A different solution could be to make the grab asynchronous in the agent and + * to export it as synchronous. But this seems to be less safe. + * + * To make internal grab asynchronous, change previous line as follows. + * + * if (nxagentOption(Rootless)) + * { + * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode); + * } + * else + * { + * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + * } + */ + + if (nxagentOption(Rootless) == 1) + { + /* + * FIXME: We should use the correct value + * for the cursor. Temporarily we set it + * to None. + */ + + int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, + nxagentCollectGrabPointerPredicate); + + NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window), + 1, grab -> eventMask & PointerGrabMask, + GrabModeAsync, GrabModeAsync, (grab -> confineTo) ? + nxagentWindow(grab -> confineTo) : None, + None, CurrentTime); + } + + #endif +} + +void +DeactivatePointerGrab(register DeviceIntPtr mouse) +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); + + #ifdef NXAGENT_SERVER + + if (nxagentOption(Rootless) == 1) + { + XUngrabPointer(nxagentDisplay, CurrentTime); + + if (sprite.win == ROOT) + { + mouse -> button -> state &= + ~(Button1Mask | Button2Mask | Button3Mask | + Button4Mask | Button5Mask); + } + } + + #endif +} + +void +ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(register DeviceIntPtr keybd) +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(register ClientPtr client) +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * This is not necessary if we export grab to X as asynchronous. + * + * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard && + * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard) + * { + * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime); + * } + */ + + return Success; +} + +void +ReleaseActiveGrabs(ClientPtr client) +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +int +TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, + Mask filter, GrabPtr grab) +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); + fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint + ((deviceKeyButtonPointer*)pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { +#ifdef SMART_SCHEDULE + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; +#endif + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(register WindowPtr pWin, xEvent *pEvents, int count, + Mask filter, GrabPtr grab, int mskidx) +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask = 0; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) +#ifdef XKB + || (type == DeviceButtonPress) +#endif + ) && deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +#ifdef PANORAMIX +static int +XineramaTryClientEventsResult( + ClientPtr client, + GrabPtr grab, + Mask mask, + Mask filter +){ + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) return -1; + else return 1; + } + return 0; +} +#endif + +int +MaybeDeliverEventsToClient(register WindowPtr pWin, xEvent *pEvents, + int count, Mask filter, ClientPtr dontClient) +{ + register OtherClients *other; + + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + wClient(pWin), NullGrab, pWin->eventMask, filter); +#endif + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + rClient(other), NullGrab, other->mask, filter); +#endif + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xTrue; + XE_KBPTR.child = child; + XE_KBPTR.eventX = + XE_KBPTR.rootX - pWin->drawable.x; + XE_KBPTR.eventY = + XE_KBPTR.rootY - pWin->drawable.y; + } + else + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + } +} + +int +DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab, + register WindowPtr stopAt, DeviceIntPtr dev, int count) +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +int +DeliverEvents(register WindowPtr pWin, register xEvent *xE, int count, + register WindowPtr otherParent) +{ + Mask filter; + int deliveries; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return count; +#endif + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + + +static Bool +PointInBorderSize(WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(POINT_IN_REGION(sprite.screen, + &sprite.windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + &box)) + return TRUE; + } + } +#endif + return FALSE; +} + +static WindowPtr +XYToWindow(int x, int y) +{ + register WindowPtr pWin; + BoxRec box; + + spriteTraceGood = 1; /* root window still there */ + + if (nxagentOption(Rootless)) + { + if (nxagentLastEnteredWindow == NULL) + { + return ROOT; + } + + pWin = ROOT->lastChild; + + while (pWin && pWin != ROOT->firstChild && pWin != nxagentLastEnteredWindow) + { + pWin = pWin->prevSib; + } + } + else + { + pWin = ROOT->firstChild; + } + + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +CheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaCheckMotion(xE); +#endif + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = XE_KBPTR.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif + sprite.hotPhys = sprite.hot; + + /* + * This code force cursor position to be inside the + * root window of the agent. We can't view a reason + * to do this and it interacts in an undesirable way + * with toggling fullscreen. + * + * if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + * (sprite.hotPhys.y != XE_KBPTR.rootY)) + * { + * (*sprite.hotPhys.pScreen->SetCursorPosition)( + * sprite.hotPhys.pScreen, + * sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + * } + */ + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +#ifdef PANORAMIX +/* This was added to support reconfiguration under Xdmx. The problem is + * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin + * other than 0,0, the information in the private sprite structure must + * be updated accordingly, or XYToWindow (and other routines) will not + * compute correctly. */ +void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) +{ + ScreenPtr pScreen = win->drawable.pScreen; + GrabPtr grab; + + if (noPanoramiXExtension) return; + + sprite.hot.x -= xoff; + sprite.hot.y -= yoff; + + sprite.hotPhys.x -= xoff; + sprite.hotPhys.y -= yoff; + + sprite.hotLimits.x1 -= xoff; + sprite.hotLimits.y1 -= yoff; + sprite.hotLimits.x2 -= xoff; + sprite.hotLimits.y2 -= yoff; + + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff); + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff); + + /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +DefineInitialRootWindow(register WindowPtr win) +{ + register ScreenPtr pScreen = win->drawable.pScreen; + #ifdef VIEWPORT_FRAME + extern void nxagentInitViewportFrame(ScreenPtr, WindowPtr); + #endif + extern int nxagentShadowInit(ScreenPtr, WindowPtr); + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = win; + sprite.current = wCursor (win); + sprite.current->refcnt++; + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.confineWin = NullWindow; +#ifdef SHAPE + sprite.hotShape = NullRegion; +#endif + sprite.screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_NULL(pScreen, &sprite.Reg1); + REGION_NULL(pScreen, &sprite.Reg2); + } +#endif + + #ifdef VIEWPORT_FRAME + nxagentInitViewportFrame(pScreen, win); + #endif + + if (nxagentOption(Shadow)) + { + if (nxagentShadowInit(pScreen, win) == -1) + { + FatalError("Failed to connect to display '%s'", nxagentShadowDisplayName); + } + } +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +void +WindowHasNewCursor(WindowPtr pWin) +{ + PostNewCursor(); +} + +void +NewCurrentScreen(ScreenPtr newScreen, int x, int y) +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + panoramiXdataPtr[0].x; + sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + panoramiXdataPtr[0].y; + if (newScreen != sprite.screen) { + sprite.screen = newScreen; + /* Make sure we tell the DDX to update its copy of the screen */ + if(sprite.confineWin) + XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + else + XineramaConfineCursorToWindow(WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get + told of the pointer warp so we reposition it here */ + if(!syncEvents.playingEvents) + (*sprite.screen->SetCursorPosition)(sprite.screen, + sprite.hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x, + sprite.hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + } + } else +#endif + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +#ifdef PANORAMIX + +static Bool +XineramaPointInWindowIsVisible( + WindowPtr pWin, + int x, + int y +) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + int i, xoff, yoff; + + if (!pWin->realized) return FALSE; + + if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + if(!XineramaSetWindowPntrs(pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; + + for(i = 1; i < PanoramiXNumScreens; i++) { + pWin = sprite.windows[i]; + pScreen = pWin->drawable.pScreen; + x = xoff - panoramiXdataPtr[i].x; + y = yoff - panoramiXdataPtr[i].y; + + if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return TRUE; + + } + + return FALSE; +} + +static int +XineramaWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + + REQUEST(xWarpPointerReq); + + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if(source == WindowTable[0]) { + winX -= panoramiXdataPtr[0].x; + winY -= panoramiXdataPtr[0].y; + } + if (x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !XineramaPointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) { + x = dest->drawable.x; + y = dest->drawable.y; + if(dest == WindowTable[0]) { + x -= panoramiXdataPtr[0].x; + y -= panoramiXdataPtr[0].y; + } + } + + x += stuff->dstX; + y += stuff->dstY; + + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + + XineramaSetCursorPosition(x, y, TRUE); + + return Success; +} + +#endif + + +int +ProcWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaWarpPointer(client); +#endif + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = sprite.hotPhys.pScreen; + + x += stuff->dstX; + y += stuff->dstY; + + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#if defined(SHAPE) + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + return TRUE; + } + } +#endif + return FALSE; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +CheckPassiveGrabsOnWindow( + WindowPtr pWin, + register DeviceIntPtr device, + register xEvent *xE, + int count) +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if ((device == grab->modifierDevice) && + ((xE->u.u.type == KeyPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceKeyPress) +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) + { +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + XE_KBPTR.state &= 0x1f00; + XE_KBPTR.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/** +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(register DeviceIntPtr device, register xEvent *xE, + int checkFirst, int count) +{ + register int i; + register WindowPtr pWin = NULL; + register FocusClassPtr focus = device->focus; + + if (((xE->u.u.type == ButtonPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceButtonPress) +#endif + ) && (device->button->buttonsDown != 1)) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev, + Bool deactivateGrab, int count) +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#else +ProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#endif +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; +#ifdef XEVIE + static Window rootWin = 0; + + if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + if((xE->u.u.type == KeyPress && (*kptr & bit)) || + (xE->u.u.type == KeyRelease && !(*kptr & bit))) + {} else { +#ifdef XKB + if(!noXkbExtension) + xevieKBEventSent = 1; +#endif + if(!xevieKBEventSent) + { + xeviekb = keybd; + if(!rootWin) { + rootWin = GetCurrentRootWindow()->drawable.id; + } + xE->u.keyButtonPointer.event = xeviewin->drawable.id; + xE->u.keyButtonPointer.root = rootWin; + xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild-> +drawable.id:0; + xE->u.keyButtonPointer.rootX = xeviehot.x; + xE->u.keyButtonPointer.rootY = xeviehot.y; + xE->u.keyButtonPointer.state = keyc->state; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); +#ifdef XKB + if(noXkbExtension) +#endif + return; + } else { + xevieKBEventSent = 0; + } + } + } +#endif + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } +#ifdef XEVIE + /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */ + if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type] +#ifdef XKB + && !noXkbExtension +#endif + ))) +#endif + XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#if defined(XKB) && defined(XEVIE) + if(!noXkbExtension && !xeviegrabState && + xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + switch(xE->u.u.type) { + case KeyPress: *kptr &= ~bit; break; + case KeyRelease: *kptr |= bit; break; + } + } +#endif + +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); +} + +#ifdef XKB +/* This function is used to set the key pressed or key released state - + this is only used when the pressing of keys does not cause + CoreProcessKeyEvent to be called, as in for example Mouse Keys. +*/ +void +FixKeyState (register xEvent *xE, register DeviceIntPtr keybd) +{ + int key, bit; + register BYTE *kptr; + register KeyClassPtr keyc = keybd->key; + + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("FixKeyState: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + *kptr |= bit; + break; + case KeyRelease: + *kptr &= ~bit; + break; + default: + FatalError("Impossible keyboard event"); + } +} +#endif + +void +#ifdef XKB +CoreProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#else +ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#endif +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi; + + xkbi = inputInfo.keyboard->key->xkbInfo; +#endif +#ifdef XEVIE + if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && + (xevieMask & xevieFilters[xE->u.u.type])) { + if(xevieEventSent) + xevieEventSent = 0; + else { + xeviemouse = mouse; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); + return; + } + } +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + if (!(*kptr & bit)) + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (*kptr & bit) + --butc->buttonsDown; + if (!butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +/** + * + * \param value must conform to DeleteType + */ +int +OtherClientGone(pointer value, XID id) +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(register WindowPtr pWin, register ClientPtr client, Mask mask) +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#ifdef SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#ifdef SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +int +EventSuppressForWindow(register WindowPtr pWin, register ClientPtr client, + Mask mask, Bool *checkOptional) +{ + register int i, free; + + if ((mask & ~PropagateMask) && !permitOldBugs) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +CommonAncestor( + register WindowPtr a, + register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +EnterLeaveEvent( + int type, + int mode, + int detail, + register WindowPtr pWin, + Window child) +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XCSECURITY + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin) +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XCSECURITY + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +FocusInEvents( + DeviceIntPtr dev, + WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, + int mode, int detail, + Bool doAncestor) +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +FocusOutEvents( + DeviceIntPtr dev, + WindowPtr child, WindowPtr ancestor, + int mode, int detail, + Bool doAncestor) +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; iparent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); + else +#endif + for (i=0; iparent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +SetInputFocus( + ClientPtr client, + DeviceIntPtr dev, + Window focusID, + CARD8 revertTo, + Time ctime, + Bool followOK) +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)(long)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(ClientPtr client) +{ + xGetInputFocusReply rep; + /* REQUEST(xReq); */ + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(ClientPtr client) +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(register ClientPtr client, register DeviceIntPtr dev, + unsigned this_mode, unsigned other_mode, Window grabWindow, + unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status) +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(ClientPtr client) +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(ClientPtr client) +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if(stuff->id == rep.root) { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +void +CloseDownEvents(void) +{ + xfree(spriteTrace); + spriteTrace = NULL; + spriteTraceSize = 0; +} + +int +ProcSendEvent(ClientPtr client) +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + +#ifdef NXAGENT_CLIPBOARD + + if (stuff -> event.u.u.type == SelectionNotify) + { + extern int nxagentSendNotify(xEvent*); + if (nxagentSendNotify(&stuff->event) == 1) + return Success; + } +#endif + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32 && + !permitOldBugs) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(ClientPtr client) +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, + NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + + +int +ProcGrabButton(ClientPtr client) +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + permitOldBugs ? (Mask)(stuff->eventMask | + ButtonPressMask | ButtonReleaseMask) : + (Mask)stuff->eventMask, + (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, + (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers, + ButtonPress, stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(ClientPtr client) +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/** + * Call this whenever some window at or below pWin has changed geometry + */ +void +CheckCursorConfinement(WindowPtr pWin) +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; +#endif + + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(confineTo)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(WindowPtr pWin, ClientPtr client) +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(ClientPtr client) +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + Bool displayed; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; +#ifdef PANORAMIX + if(!noPanoramiXExtension) + displayed = (pscr == sprite.screen); + else +#endif + displayed = (pscr == sprite.hotPhys.pScreen); + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && displayed); + } + return (Success); +} + +void +WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) +{ +#ifdef PANORAMIX + xEvent eventCopy; +#endif + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + +#ifdef PANORAMIX + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + { + switch(events->u.u.type) { + case MotionNotify: + case ButtonPress: + case ButtonRelease: + case KeyPress: + case KeyRelease: + case EnterNotify: + case LeaveNotify: + /* + When multiple clients want the same event DeliverEventsToWindow + passes the same event structure multiple times so we can't + modify the one passed to us + */ + count = 1; /* should always be 1 */ + memcpy(&eventCopy, events, sizeof(xEvent)); + eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) + { + eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; + } + events = &eventCopy; + break; + default: break; + } + } +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.NX.original new file mode 100644 index 000000000..91e290996 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.NX.original @@ -0,0 +1,4827 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.17 2005/08/25 22:11:04 anholt Exp $ */ +/* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/***************************************************************** + +Copyright 2003-2005 Sun Microsystems, 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, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +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 +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +******************************************************************/ + +/* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "Xlib.h" +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "globals.h" + +#ifdef XKB +#include +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +#endif + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif + +#ifdef XEVIE +extern WindowPtr *WindowTable; +extern int xevieFlag; +extern int xevieClientIndex; +extern DeviceIntPtr xeviemouse; +extern DeviceIntPtr xeviekb; +extern Mask xevieMask; +extern Mask xevieFilters[128]; +extern int xevieEventSent; +extern int xevieKBEventSent; +int xeviegrabState = 0; +xEvent *xeviexE; +#endif + +#include +#include "exevents.h" +#include "extnsionst.h" + +#include "dixevents.h" +#include "dixgrabs.h" +#include "../../dix/dispatch.h" + +#include "NXlib.h" + +#include "Events.h" +#include "Windows.h" +#include "Args.h" + +extern Display *nxagentDisplay; + +extern WindowPtr nxagentLastEnteredWindow; + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the ButtonMotionMasks are equal + * to the corresponding ButtonMasks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define XE_KBPTR (xE->u.keyButtonPointer) + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +CallbackListPtr EventCallback; +CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif +} sprite; /* info about the cursor sprite */ + +#ifdef XEVIE +WindowPtr xeviewin; +HotSpot xeviehot; +#endif + +static void DoEnterLeaveEvents( + WindowPtr fromWin, + WindowPtr toWin, + int mode +); + +static WindowPtr XYToWindow( + int x, + int y +); + +extern int lastEvent; + +static Mask lastEventMask; + +#ifdef XINPUT +extern int DeviceMotionNotify; +#endif + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x7c /* key and button events */ +}; + +#ifdef PANORAMIX + +static void ConfineToShape(RegionPtr shape, int *px, int *py); +static void SyntheticMotion(int x, int y); +static void PostNewCursor(void); + +static Bool +XineramaSetCursorPosition( + int x, + int y, + Bool generateEvent +){ + ScreenPtr pScreen; + BoxRec box; + int i; + + /* x,y are in Screen 0 coordinates. We need to decide what Screen + to send the message too and what the coordinates relative to + that screen are. */ + + pScreen = sprite.screen; + x += panoramiXdataPtr[0].x; + y += panoramiXdataPtr[0].y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) + { + FOR_NSCREENS(i) + { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) + { + pScreen = screenInfo.screens[i]; + break; + } + } + } + + sprite.screen = pScreen; + sprite.hotPhys.x = x - panoramiXdataPtr[0].x; + sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + x -= panoramiXdataPtr[pScreen->myNum].x; + y -= panoramiXdataPtr[pScreen->myNum].y; + + return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); +} + + +static void +XineramaConstrainCursor(void) +{ + ScreenPtr pScreen = sprite.screen; + BoxRec newBox = sprite.physLimits; + + /* Translate the constraining box to the screen + the sprite is actually on */ + newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + + (* pScreen->ConstrainCursor)(pScreen, &newBox); +} + +static void +XineramaCheckPhysLimits( + CursorPtr cursor, + Bool generateEvents +){ + HotSpot new; + + if (!cursor) + return; + + new = sprite.hotPhys; + + /* I don't care what the DDX has to say about it */ + sprite.physLimits = sprite.hotLimits; + + /* constrain the pointer to those limits */ + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) /* more work if the shape is a mess */ + ConfineToShape(sprite.hotShape, &new.x, &new.y); + + if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + XineramaSetCursorPosition (new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } + + /* Tell DDX what the limits are */ + XineramaConstrainCursor(); +} + + +static Bool +XineramaSetWindowPntrs(WindowPtr pWin) +{ + if(pWin == WindowTable[0]) { + memcpy(sprite.windows, WindowTable, + PanoramiXNumScreens*sizeof(WindowPtr)); + } else { + PanoramiXRes *win; + int i; + + win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); + + if(!win) + return FALSE; + + for(i = 0; i < PanoramiXNumScreens; i++) { + sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!sprite.windows[i]) /* window is being unmapped */ + return FALSE; + } + } + return TRUE; +} + +static void +XineramaCheckVirtualMotion( + QdEventPtr qe, + WindowPtr pWin +){ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + int x, y, off_x, off_y, i; + BoxRec lims; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg2, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + + if (sprite.hot.x < lims.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y2 - 1; + + if (REGION_NUM_RECTS(&sprite.Reg2) > 1) + ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +} + + +static Bool +XineramaCheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + /* Motion events entering DIX get translated to Screen 0 + coordinates. Replayed events have already been + translated since they've entered DIX before */ + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = XE_KBPTR.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + XineramaSetCursorPosition( + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + + +static void +XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +{ + + if (syncEvents.playingEvents) + { + XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + int x, y, off_x, off_y, i; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg1, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + + if(REGION_NUM_RECTS(&sprite.Reg1) > 1) + sprite.hotShape = &sprite.Reg1; + else + sprite.hotShape = NullRegion; + + sprite.confined = FALSE; + sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + + XineramaCheckPhysLimits(sprite.current, generateEvents); + } +} + + +static void +XineramaChangeToCursor(CursorPtr cursor) +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(cursor, FALSE); + (*sprite.screen->DisplayCursor)(sprite.screen, cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + + +#endif /* PANORAMIX */ + +void +SetMaskForEvent(Mask mask, int event) +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +void +SetCriticalEvent(int event) +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +SyntheticMotion(int x, int y) +{ + xEvent xE; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x; + y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +ConfineToShape(RegionPtr shape, int *px, int *py) +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +CheckPhysLimits( + CursorPtr cursor, + Bool generateEvents, + Bool confineToScreen, + ScreenPtr pScreen) +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +CheckVirtualMotion( + register QdEventPtr qe, + register WindowPtr pWin) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaCheckVirtualMotion(qe, pWin); + return; + } +#endif + if (qe) + { + sprite.hot.pScreen = qe->pScreen; +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; +#ifdef XEVIE + xeviehot.x = xeviehot.y = 0; +#endif + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaConfineCursorToWindow(pWin, generateEvents); + return; + } +#endif + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +ChangeToCursor(CursorPtr cursor) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaChangeToCursor(cursor); + return; + } +#endif + + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, sprite.confined, + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(register WindowPtr a, register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +PostNewCursor(void) +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +void +GetSpritePosition(int *px, int *py) +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#ifdef PANORAMIX +int +XineramaGetCursorScreen() +{ + if(!noPanoramiXExtension) { + return sprite.screen->myNum; + } else { + return 0; + } +} +#endif /* PANORAMIX */ + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +MonthChangedOrBadTime(register xEvent *xE) +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) + currentTime.months++; + else + XE_KBPTR.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(register xEvent *xE) +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + +#ifdef XKB + /* Fix for key repeating bug. */ + if (device->key != NULL && device->key->xkbInfo != NULL && + xE->u.u.type == KeyRelease) + AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); +#endif + + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + } +#endif + sprite.hotPhys.x = XE_KBPTR.rootX; + sprite.hotPhys.y = XE_KBPTR.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = XE_KBPTR.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +PlayReleasedEvents(void) +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +FreezeThaw(register DeviceIntPtr dev, Bool frozen) +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + + w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < spriteTraceGood; i++) + { + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + } + goto playmore; + } + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +#ifdef RANDR +void +ScreenRestructured (ScreenPtr pScreen) +{ + GrabPtr grab; + + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab, + TimeStamp time, Bool autoGrab) +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + + #ifdef NXAGENT_SERVER + + /* + * If grab is synchronous, events are delivered to clients only if they send + * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the + * delivered event is saved in a queue and replayed later, when grab is released. + * We should export sync grab to X as async in order to avoid events to be + * queued twice, in the agent and in the X server. This solution have a drawback: + * replayed events are not delivered to that application that are not clients of + * the agent. + * A different solution could be to make the grab asynchronous in the agent and + * to export it as synchronous. But this seems to be less safe. + * + * To make internal grab asynchronous, change previous line as follows. + * + * if (nxagentOption(Rootless)) + * { + * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode); + * } + * else + * { + * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); + * } + */ + + if (nxagentOption(Rootless) == 1) + { + /* + * FIXME: We should use the correct value + * for the cursor. Temporarily we set it + * to None. + */ + + int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource, + nxagentCollectGrabPointerPredicate); + + NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window), + 1, grab -> eventMask & PointerGrabMask, + GrabModeAsync, GrabModeAsync, (grab -> confineTo) ? + nxagentWindow(grab -> confineTo) : None, + None, CurrentTime); + } + + #endif +} + +void +DeactivatePointerGrab(register DeviceIntPtr mouse) +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); + + #ifdef NXAGENT_SERVER + + if (nxagentOption(Rootless) == 1) + { + XUngrabPointer(nxagentDisplay, CurrentTime); + + if (sprite.win == ROOT) + { + mouse -> button -> state &= + ~(Button1Mask | Button2Mask | Button3Mask | + Button4Mask | Button5Mask); + } + } + + #endif +} + +void +ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(register DeviceIntPtr keybd) +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(register ClientPtr client) +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + + /* + * This is not necessary if we export grab to X as asynchronous. + * + * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard && + * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard) + * { + * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime); + * } + */ + + return Success; +} + +void +ReleaseActiveGrabs(ClientPtr client) +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +int +TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, + Mask filter, GrabPtr grab) +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); + fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint + ((deviceKeyButtonPointer*)pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { +#ifdef SMART_SCHEDULE + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; +#endif + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(register WindowPtr pWin, xEvent *pEvents, int count, + Mask filter, GrabPtr grab, int mskidx) +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask = 0; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) +#ifdef XKB + || (type == DeviceButtonPress) +#endif + ) && deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +#ifdef PANORAMIX +static int +XineramaTryClientEventsResult( + ClientPtr client, + GrabPtr grab, + Mask mask, + Mask filter +){ + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) return -1; + else return 1; + } + return 0; +} +#endif + +int +MaybeDeliverEventsToClient(register WindowPtr pWin, xEvent *pEvents, + int count, Mask filter, ClientPtr dontClient) +{ + register OtherClients *other; + + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + wClient(pWin), NullGrab, pWin->eventMask, filter); +#endif + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + rClient(other), NullGrab, other->mask, filter); +#endif + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xTrue; + XE_KBPTR.child = child; + XE_KBPTR.eventX = + XE_KBPTR.rootX - pWin->drawable.x; + XE_KBPTR.eventY = + XE_KBPTR.rootY - pWin->drawable.y; + } + else + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + } +} + +int +DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab, + register WindowPtr stopAt, DeviceIntPtr dev, int count) +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +int +DeliverEvents(register WindowPtr pWin, register xEvent *xE, int count, + register WindowPtr otherParent) +{ + Mask filter; + int deliveries; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return count; +#endif + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + + +static Bool +PointInBorderSize(WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(POINT_IN_REGION(sprite.screen, + &sprite.windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + &box)) + return TRUE; + } + } +#endif + return FALSE; +} + +static WindowPtr +XYToWindow(int x, int y) +{ + register WindowPtr pWin; + BoxRec box; + + spriteTraceGood = 1; /* root window still there */ + + if (nxagentOption(Rootless)) + { + if (nxagentLastEnteredWindow == NULL) + { + return ROOT; + } + + pWin = ROOT->lastChild; + + while (pWin && pWin != ROOT->firstChild && pWin != nxagentLastEnteredWindow) + { + pWin = pWin->prevSib; + } + } + else + { + pWin = ROOT->firstChild; + } + + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +CheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaCheckMotion(xE); +#endif + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = XE_KBPTR.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif + sprite.hotPhys = sprite.hot; + + /* + * This code force cursor position to be inside the + * root window of the agent. We can't view a reason + * to do this and it interacts in an undesirable way + * with toggling fullscreen. + * + * if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + * (sprite.hotPhys.y != XE_KBPTR.rootY)) + * { + * (*sprite.hotPhys.pScreen->SetCursorPosition)( + * sprite.hotPhys.pScreen, + * sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + * } + */ + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +#ifdef PANORAMIX +/* This was added to support reconfiguration under Xdmx. The problem is + * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin + * other than 0,0, the information in the private sprite structure must + * be updated accordingly, or XYToWindow (and other routines) will not + * compute correctly. */ +void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) +{ + ScreenPtr pScreen = win->drawable.pScreen; + GrabPtr grab; + + if (noPanoramiXExtension) return; + + sprite.hot.x -= xoff; + sprite.hot.y -= yoff; + + sprite.hotPhys.x -= xoff; + sprite.hotPhys.y -= yoff; + + sprite.hotLimits.x1 -= xoff; + sprite.hotLimits.y1 -= yoff; + sprite.hotLimits.x2 -= xoff; + sprite.hotLimits.y2 -= yoff; + + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff); + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff); + + /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +DefineInitialRootWindow(register WindowPtr win) +{ + register ScreenPtr pScreen = win->drawable.pScreen; + #ifdef VIEWPORT_FRAME + extern void nxagentInitViewportFrame(ScreenPtr, WindowPtr); + #endif + extern int nxagentShadowInit(ScreenPtr, WindowPtr); + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = win; + sprite.current = wCursor (win); + sprite.current->refcnt++; + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.confineWin = NullWindow; +#ifdef SHAPE + sprite.hotShape = NullRegion; +#endif + sprite.screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_NULL(pScreen, &sprite.Reg1); + REGION_NULL(pScreen, &sprite.Reg2); + } +#endif + + #ifdef VIEWPORT_FRAME + nxagentInitViewportFrame(pScreen, win); + #endif + + if (nxagentOption(Shadow)) + { + if (nxagentShadowInit(pScreen, win) == -1) + { + FatalError("Failed to connect to display '%s'", nxagentShadowDisplayName); + } + } +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +void +WindowHasNewCursor(WindowPtr pWin) +{ + PostNewCursor(); +} + +void +NewCurrentScreen(ScreenPtr newScreen, int x, int y) +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + panoramiXdataPtr[0].x; + sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + panoramiXdataPtr[0].y; + if (newScreen != sprite.screen) { + sprite.screen = newScreen; + /* Make sure we tell the DDX to update its copy of the screen */ + if(sprite.confineWin) + XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + else + XineramaConfineCursorToWindow(WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get + told of the pointer warp so we reposition it here */ + if(!syncEvents.playingEvents) + (*sprite.screen->SetCursorPosition)(sprite.screen, + sprite.hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x, + sprite.hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + } + } else +#endif + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +#ifdef PANORAMIX + +static Bool +XineramaPointInWindowIsVisible( + WindowPtr pWin, + int x, + int y +) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + int i, xoff, yoff; + + if (!pWin->realized) return FALSE; + + if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + if(!XineramaSetWindowPntrs(pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; + + for(i = 1; i < PanoramiXNumScreens; i++) { + pWin = sprite.windows[i]; + pScreen = pWin->drawable.pScreen; + x = xoff - panoramiXdataPtr[i].x; + y = yoff - panoramiXdataPtr[i].y; + + if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return TRUE; + + } + + return FALSE; +} + +static int +XineramaWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + + REQUEST(xWarpPointerReq); + + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if(source == WindowTable[0]) { + winX -= panoramiXdataPtr[0].x; + winY -= panoramiXdataPtr[0].y; + } + if (x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !XineramaPointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) { + x = dest->drawable.x; + y = dest->drawable.y; + if(dest == WindowTable[0]) { + x -= panoramiXdataPtr[0].x; + y -= panoramiXdataPtr[0].y; + } + } + + x += stuff->dstX; + y += stuff->dstY; + + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + + XineramaSetCursorPosition(x, y, TRUE); + + return Success; +} + +#endif + + +int +ProcWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaWarpPointer(client); +#endif + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = sprite.hotPhys.pScreen; + + x += stuff->dstX; + y += stuff->dstY; + + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#if defined(SHAPE) + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + return TRUE; + } + } +#endif + return FALSE; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +CheckPassiveGrabsOnWindow( + WindowPtr pWin, + register DeviceIntPtr device, + register xEvent *xE, + int count) +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if ((device == grab->modifierDevice) && + ((xE->u.u.type == KeyPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceKeyPress) +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) + { +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + XE_KBPTR.state &= 0x1f00; + XE_KBPTR.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/** +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(register DeviceIntPtr device, register xEvent *xE, + int checkFirst, int count) +{ + register int i; + register WindowPtr pWin = NULL; + register FocusClassPtr focus = device->focus; + + if (((xE->u.u.type == ButtonPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceButtonPress) +#endif + ) && (device->button->buttonsDown != 1)) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev, + Bool deactivateGrab, int count) +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#else +ProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#endif +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; +#ifdef XEVIE + static Window rootWin = 0; + + if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + if((xE->u.u.type == KeyPress && (*kptr & bit)) || + (xE->u.u.type == KeyRelease && !(*kptr & bit))) + {} else { +#ifdef XKB + if(!noXkbExtension) + xevieKBEventSent = 1; +#endif + if(!xevieKBEventSent) + { + xeviekb = keybd; + if(!rootWin) { + rootWin = GetCurrentRootWindow()->drawable.id; + } + xE->u.keyButtonPointer.event = xeviewin->drawable.id; + xE->u.keyButtonPointer.root = rootWin; + xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild-> +drawable.id:0; + xE->u.keyButtonPointer.rootX = xeviehot.x; + xE->u.keyButtonPointer.rootY = xeviehot.y; + xE->u.keyButtonPointer.state = keyc->state; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); +#ifdef XKB + if(noXkbExtension) +#endif + return; + } else { + xevieKBEventSent = 0; + } + } + } +#endif + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } +#ifdef XEVIE + /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */ + if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type] +#ifdef XKB + && !noXkbExtension +#endif + ))) +#endif + XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#if defined(XKB) && defined(XEVIE) + if(!noXkbExtension && !xeviegrabState && + xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + switch(xE->u.u.type) { + case KeyPress: *kptr &= ~bit; break; + case KeyRelease: *kptr |= bit; break; + } + } +#endif + +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); +} + +#ifdef XKB +/* This function is used to set the key pressed or key released state - + this is only used when the pressing of keys does not cause + CoreProcessKeyEvent to be called, as in for example Mouse Keys. +*/ +void +FixKeyState (register xEvent *xE, register DeviceIntPtr keybd) +{ + int key, bit; + register BYTE *kptr; + register KeyClassPtr keyc = keybd->key; + + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("FixKeyState: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + *kptr |= bit; + break; + case KeyRelease: + *kptr &= ~bit; + break; + default: + FatalError("Impossible keyboard event"); + } +} +#endif + +void +#ifdef XKB +CoreProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#else +ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#endif +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi; + + xkbi = inputInfo.keyboard->key->xkbInfo; +#endif +#ifdef XEVIE + if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && + (xevieMask & xevieFilters[xE->u.u.type])) { + if(xevieEventSent) + xevieEventSent = 0; + else { + xeviemouse = mouse; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); + return; + } + } +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + if (!(*kptr & bit)) + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (*kptr & bit) + --butc->buttonsDown; + if (!butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +/** + * + * \param value must conform to DeleteType + */ +int +OtherClientGone(pointer value, XID id) +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(register WindowPtr pWin, register ClientPtr client, Mask mask) +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#ifdef SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#ifdef SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +int +EventSuppressForWindow(register WindowPtr pWin, register ClientPtr client, + Mask mask, Bool *checkOptional) +{ + register int i, free; + + if ((mask & ~PropagateMask) && !permitOldBugs) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +CommonAncestor( + register WindowPtr a, + register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +EnterLeaveEvent( + int type, + int mode, + int detail, + register WindowPtr pWin, + Window child) +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XCSECURITY + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin) +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XCSECURITY + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +FocusInEvents( + DeviceIntPtr dev, + WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, + int mode, int detail, + Bool doAncestor) +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +FocusOutEvents( + DeviceIntPtr dev, + WindowPtr child, WindowPtr ancestor, + int mode, int detail, + Bool doAncestor) +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; iparent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); + else +#endif + for (i=0; iparent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +SetInputFocus( + ClientPtr client, + DeviceIntPtr dev, + Window focusID, + CARD8 revertTo, + Time ctime, + Bool followOK) +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)(long)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(ClientPtr client) +{ + xGetInputFocusReply rep; + /* REQUEST(xReq); */ + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(ClientPtr client) +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(register ClientPtr client, register DeviceIntPtr dev, + unsigned this_mode, unsigned other_mode, Window grabWindow, + unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status) +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(ClientPtr client) +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(ClientPtr client) +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if(stuff->id == rep.root) { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +void +CloseDownEvents(void) +{ + xfree(spriteTrace); + spriteTrace = NULL; + spriteTraceSize = 0; +} + +int +ProcSendEvent(ClientPtr client) +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + +#ifdef NXAGENT_CLIPBOARD + + if (stuff -> event.u.u.type == SelectionNotify) + { + extern int nxagentSendNotify(xEvent*); + if (nxagentSendNotify(&stuff->event) == 1) + return Success; + } +#endif + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32 && + !permitOldBugs) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(ClientPtr client) +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, + NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + + +int +ProcGrabButton(ClientPtr client) +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + permitOldBugs ? (Mask)(stuff->eventMask | + ButtonPressMask | ButtonReleaseMask) : + (Mask)stuff->eventMask, + (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, + (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers, + ButtonPress, stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(ClientPtr client) +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/** + * Call this whenever some window at or below pWin has changed geometry + */ +void +CheckCursorConfinement(WindowPtr pWin) +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; +#endif + + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(confineTo)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(WindowPtr pWin, ClientPtr client) +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(ClientPtr client) +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + Bool displayed; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; +#ifdef PANORAMIX + if(!noPanoramiXExtension) + displayed = (pscr == sprite.screen); + else +#endif + displayed = (pscr == sprite.hotPhys.pScreen); + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && displayed); + } + return (Success); +} + +void +WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) +{ +#ifdef PANORAMIX + xEvent eventCopy; +#endif + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + +#ifdef PANORAMIX + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + { + switch(events->u.u.type) { + case MotionNotify: + case ButtonPress: + case ButtonRelease: + case KeyPress: + case KeyRelease: + case EnterNotify: + case LeaveNotify: + /* + When multiple clients want the same event DeliverEventsToWindow + passes the same event structure multiple times so we can't + modify the one passed to us + */ + count = 1; /* should always be 1 */ + memcpy(&eventCopy, events, sizeof(xEvent)); + eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) + { + eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; + } + events = &eventCopy; + break; + default: break; + } + } +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.X.original new file mode 100644 index 000000000..4373673f9 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.X.original @@ -0,0 +1,4670 @@ +/* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.17 2005/08/25 22:11:04 anholt Exp $ */ +/* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/***************************************************************** + +Copyright 2003-2005 Sun Microsystems, 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, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +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 +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +******************************************************************/ + +/* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "misc.h" +#include "resource.h" +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" + +#include "dixstruct.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "globals.h" + +#ifdef XKB +#include +extern Bool XkbFilterEvents(ClientPtr, int, xEvent *); +#endif + +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif + +#ifdef XEVIE +extern WindowPtr *WindowTable; +extern int xevieFlag; +extern int xevieClientIndex; +extern DeviceIntPtr xeviemouse; +extern DeviceIntPtr xeviekb; +extern Mask xevieMask; +extern Mask xevieFilters[128]; +extern int xevieEventSent; +extern int xevieKBEventSent; +int xeviegrabState = 0; +xEvent *xeviexE; +#endif + +#include +#include "exevents.h" +#include "extnsionst.h" + +#include "dixevents.h" +#include "dixgrabs.h" +#include "dispatch.h" + +#define EXTENSION_EVENT_BASE 64 + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) +#define AllButtonsMask ( \ + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) +#define MotionMask ( \ + PointerMotionMask | Button1MotionMask | \ + Button2MotionMask | Button3MotionMask | Button4MotionMask | \ + Button5MotionMask | ButtonMotionMask ) +#define PropagateMask ( \ + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ + MotionMask ) +#define PointerGrabMask ( \ + ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask | \ + PointerMotionHintMask | KeymapStateMask | \ + MotionMask ) +#define AllModifiersMask ( \ + ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ + Mod3Mask | Mod4Mask | Mod5Mask ) +#define AllEventMasks (lastEventMask|(lastEventMask-1)) +/* + * The following relies on the fact that the ButtonMotionMasks are equal + * to the corresponding ButtonMasks from the current modifier/button state. + */ +#define Motion_Filter(class) (PointerMotionMask | \ + (class)->state | (class)->motionMask) + + +#define WID(w) ((w) ? ((w)->drawable.id) : 0) + +#define XE_KBPTR (xE->u.keyButtonPointer) + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +CallbackListPtr EventCallback; +CallbackListPtr DeviceEventCallback; + +#define DNPMCOUNT 8 + +Mask DontPropagateMasks[DNPMCOUNT]; +static int DontPropagateRefCnts[DNPMCOUNT]; + +#ifdef DEBUG +static debug_events = 0; +#endif +InputInfo inputInfo; + +static struct { + QdEventPtr pending, *pendtail; + DeviceIntPtr replayDev; /* kludgy rock to put flag for */ + WindowPtr replayWin; /* ComputeFreezes */ + Bool playingEvents; + TimeStamp time; +} syncEvents; + +/* + * The window trace information is used to avoid having to compute all the + * windows between the root and the current pointer window each time a button + * or key goes down. The grabs on each of those windows must be checked. + */ +static WindowPtr *spriteTrace = (WindowPtr *)NULL; +#define ROOT spriteTrace[0] +static int spriteTraceSize = 0; +static int spriteTraceGood; + +static struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif +} sprite; /* info about the cursor sprite */ + +#ifdef XEVIE +WindowPtr xeviewin; +HotSpot xeviehot; +#endif + +static void DoEnterLeaveEvents( + WindowPtr fromWin, + WindowPtr toWin, + int mode +); + +static WindowPtr XYToWindow( + int x, + int y +); + +extern int lastEvent; + +static Mask lastEventMask; + +#ifdef XINPUT +extern int DeviceMotionNotify; +#endif + +#define CantBeFiltered NoEventMask +static Mask filters[128] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ + EnterWindowMask, /* EnterNotify */ + LeaveWindowMask, /* LeaveNotify */ + FocusChangeMask, /* FocusIn */ + FocusChangeMask, /* FocusOut */ + KeymapStateMask, /* KeymapNotify */ + ExposureMask, /* Expose */ + CantBeFiltered, /* GraphicsExpose */ + CantBeFiltered, /* NoExpose */ + VisibilityChangeMask, /* VisibilityNotify */ + SubstructureNotifyMask, /* CreateNotify */ + StructureAndSubMask, /* DestroyNotify */ + StructureAndSubMask, /* UnmapNotify */ + StructureAndSubMask, /* MapNotify */ + SubstructureRedirectMask, /* MapRequest */ + StructureAndSubMask, /* ReparentNotify */ + StructureAndSubMask, /* ConfigureNotify */ + SubstructureRedirectMask, /* ConfigureRequest */ + StructureAndSubMask, /* GravityNotify */ + ResizeRedirectMask, /* ResizeRequest */ + StructureAndSubMask, /* CirculateNotify */ + SubstructureRedirectMask, /* CirculateRequest */ + PropertyChangeMask, /* PropertyNotify */ + CantBeFiltered, /* SelectionClear */ + CantBeFiltered, /* SelectionRequest */ + CantBeFiltered, /* SelectionNotify */ + ColormapChangeMask, /* ColormapNotify */ + CantBeFiltered, /* ClientMessage */ + CantBeFiltered /* MappingNotify */ +}; + +static CARD8 criticalEvents[32] = +{ + 0x7c /* key and button events */ +}; + +#ifdef PANORAMIX + +static void ConfineToShape(RegionPtr shape, int *px, int *py); +static void SyntheticMotion(int x, int y); +static void PostNewCursor(void); + +static Bool +XineramaSetCursorPosition( + int x, + int y, + Bool generateEvent +){ + ScreenPtr pScreen; + BoxRec box; + int i; + + /* x,y are in Screen 0 coordinates. We need to decide what Screen + to send the message too and what the coordinates relative to + that screen are. */ + + pScreen = sprite.screen; + x += panoramiXdataPtr[0].x; + y += panoramiXdataPtr[0].y; + + if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) + { + FOR_NSCREENS(i) + { + if(i == pScreen->myNum) + continue; + if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) + { + pScreen = screenInfo.screens[i]; + break; + } + } + } + + sprite.screen = pScreen; + sprite.hotPhys.x = x - panoramiXdataPtr[0].x; + sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + x -= panoramiXdataPtr[pScreen->myNum].x; + y -= panoramiXdataPtr[pScreen->myNum].y; + + return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); +} + + +static void +XineramaConstrainCursor(void) +{ + ScreenPtr pScreen = sprite.screen; + BoxRec newBox = sprite.physLimits; + + /* Translate the constraining box to the screen + the sprite is actually on */ + newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; + newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; + + (* pScreen->ConstrainCursor)(pScreen, &newBox); +} + +static void +XineramaCheckPhysLimits( + CursorPtr cursor, + Bool generateEvents +){ + HotSpot new; + + if (!cursor) + return; + + new = sprite.hotPhys; + + /* I don't care what the DDX has to say about it */ + sprite.physLimits = sprite.hotLimits; + + /* constrain the pointer to those limits */ + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) /* more work if the shape is a mess */ + ConfineToShape(sprite.hotShape, &new.x, &new.y); + + if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + XineramaSetCursorPosition (new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } + + /* Tell DDX what the limits are */ + XineramaConstrainCursor(); +} + + +static Bool +XineramaSetWindowPntrs(WindowPtr pWin) +{ + if(pWin == WindowTable[0]) { + memcpy(sprite.windows, WindowTable, + PanoramiXNumScreens*sizeof(WindowPtr)); + } else { + PanoramiXRes *win; + int i; + + win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); + + if(!win) + return FALSE; + + for(i = 0; i < PanoramiXNumScreens; i++) { + sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!sprite.windows[i]) /* window is being unmapped */ + return FALSE; + } + } + return TRUE; +} + +static void +XineramaCheckVirtualMotion( + QdEventPtr qe, + WindowPtr pWin +){ + + if (qe) + { + sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + int x, y, off_x, off_y, i; + BoxRec lims; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg2, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + + if (sprite.hot.x < lims.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y2 - 1; + + if (REGION_NUM_RECTS(&sprite.Reg2) > 1) + ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } +} + + +static Bool +XineramaCheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + + if (xE && !syncEvents.playingEvents) + { + /* Motion events entering DIX get translated to Screen 0 + coordinates. Replayed events have already been + translated since they've entered DIX before */ + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = XE_KBPTR.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y2 - 1; + + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + XineramaSetCursorPosition( + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + + +static void +XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +{ + + if (syncEvents.playingEvents) + { + XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + int x, y, off_x, off_y, i; + + if(!XineramaSetWindowPntrs(pWin)) + return; + + i = PanoramiXNumScreens - 1; + + REGION_COPY(sprite.screen, &sprite.Reg1, + &sprite.windows[i]->borderSize); + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + + while(i--) { + x = off_x - panoramiXdataPtr[i].x; + y = off_y - panoramiXdataPtr[i].y; + + if(x || y) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); + + REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, + &sprite.windows[i]->borderSize); + + off_x = panoramiXdataPtr[i].x; + off_y = panoramiXdataPtr[i].y; + } + + sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + + if(REGION_NUM_RECTS(&sprite.Reg1) > 1) + sprite.hotShape = &sprite.Reg1; + else + sprite.hotShape = NullRegion; + + sprite.confined = FALSE; + sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + + XineramaCheckPhysLimits(sprite.current, generateEvents); + } +} + + +static void +XineramaChangeToCursor(CursorPtr cursor) +{ + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(cursor, FALSE); + (*sprite.screen->DisplayCursor)(sprite.screen, cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + + +#endif /* PANORAMIX */ + +void +SetMaskForEvent(Mask mask, int event) +{ + if ((event < LASTEvent) || (event >= 128)) + FatalError("SetMaskForEvent: bogus event number"); + filters[event] = mask; +} + +void +SetCriticalEvent(int event) +{ + if (event >= 128) + FatalError("SetCriticalEvent: bogus event number"); + criticalEvents[event >> 3] |= 1 << (event & 7); +} + +static void +SyntheticMotion(int x, int y) +{ + xEvent xE; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x; + y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + xE.u.keyButtonPointer.rootX = x; + xE.u.keyButtonPointer.rootY = y; + if (syncEvents.playingEvents) + xE.u.keyButtonPointer.time = syncEvents.time.milliseconds; + else + xE.u.keyButtonPointer.time = currentTime.milliseconds; + xE.u.u.type = MotionNotify; + (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); +} + +#ifdef SHAPE +static void +ConfineToShape(RegionPtr shape, int *px, int *py) +{ + BoxRec box; + int x = *px, y = *py; + int incx = 1, incy = 1; + + if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + return; + box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + /* this is rather crude */ + do { + x += incx; + if (x >= box.x2) + { + incx = -1; + x = *px - 1; + } + else if (x < box.x1) + { + incx = 1; + x = *px; + y += incy; + if (y >= box.y2) + { + incy = -1; + y = *py - 1; + } + else if (y < box.y1) + return; /* should never get here! */ + } + } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + *px = x; + *py = y; +} +#endif + +static void +CheckPhysLimits( + CursorPtr cursor, + Bool generateEvents, + Bool confineToScreen, + ScreenPtr pScreen) +{ + HotSpot new; + + if (!cursor) + return; + new = sprite.hotPhys; + if (pScreen) + new.pScreen = pScreen; + else + pScreen = new.pScreen; + (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = confineToScreen; + (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); + if (new.x < sprite.physLimits.x1) + new.x = sprite.physLimits.x1; + else + if (new.x >= sprite.physLimits.x2) + new.x = sprite.physLimits.x2 - 1; + if (new.y < sprite.physLimits.y1) + new.y = sprite.physLimits.y1; + else + if (new.y >= sprite.physLimits.y2) + new.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &new.x, &new.y); +#endif + if ((pScreen != sprite.hotPhys.pScreen) || + (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + { + if (pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys = new; + (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(new.x, new.y); + } +} + +static void +CheckVirtualMotion( + register QdEventPtr qe, + register WindowPtr pWin) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaCheckVirtualMotion(qe, pWin); + return; + } +#endif + if (qe) + { + sprite.hot.pScreen = qe->pScreen; +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = qe->event->u.keyButtonPointer.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + NullWindow; + } + if (pWin) + { + BoxRec lims; + + if (sprite.hot.pScreen != pWin->drawable.pScreen) + { + sprite.hot.pScreen = pWin->drawable.pScreen; +#ifdef XEVIE + xeviehot.x = xeviehot.y = 0; +#endif + sprite.hot.x = sprite.hot.y = 0; + } + lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); + if (sprite.hot.x < lims.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x1; + else if (sprite.hot.x >= lims.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = lims.x2 - 1; + if (sprite.hot.y < lims.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y1; + else if (sprite.hot.y >= lims.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = lims.y2 - 1; +#ifdef SHAPE + if (wBoundingShape(pWin)) + ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); +#endif + if (qe) + { + qe->pScreen = sprite.hot.pScreen; + qe->event->u.keyButtonPointer.rootX = sprite.hot.x; + qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + } + } + ROOT = WindowTable[sprite.hot.pScreen->myNum]; +} + +static void +ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaConfineCursorToWindow(pWin, generateEvents); + return; + } +#endif + + if (syncEvents.playingEvents) + { + CheckVirtualMotion((QdEventPtr)NULL, pWin); + SyntheticMotion(sprite.hot.x, sprite.hot.y); + } + else + { + sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); +#ifdef SHAPE + sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + : NullRegion; +#endif + CheckPhysLimits(sprite.current, generateEvents, confineToScreen, + pScreen); + } +} + +Bool +PointerConfinedToScreen() +{ + return sprite.confined; +} + +static void +ChangeToCursor(CursorPtr cursor) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XineramaChangeToCursor(cursor); + return; + } +#endif + + if (cursor != sprite.current) + { + if ((sprite.current->bits->xhot != cursor->bits->xhot) || + (sprite.current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(cursor, FALSE, sprite.confined, + (ScreenPtr)NULL); + (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, + cursor); + FreeCursor(sprite.current, (Cursor)0); + sprite.current = cursor; + sprite.current->refcnt++; + } +} + +/* returns true if b is a descendent of a */ +Bool +IsParent(register WindowPtr a, register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (b == a) return TRUE; + return FALSE; +} + +static void +PostNewCursor(void) +{ + register WindowPtr win; + register GrabPtr grab = inputInfo.pointer->grab; + + if (syncEvents.playingEvents) + return; + if (grab) + { + if (grab->cursor) + { + ChangeToCursor(grab->cursor); + return; + } + if (IsParent(grab->window, sprite.win)) + win = sprite.win; + else + win = grab->window; + } + else + win = sprite.win; + for (; win; win = win->parent) + if (win->optional && win->optional->cursor != NullCursor) + { + ChangeToCursor(win->optional->cursor); + return; + } +} + +WindowPtr +GetCurrentRootWindow() +{ + return ROOT; +} + +WindowPtr +GetSpriteWindow() +{ + return sprite.win; +} + +CursorPtr +GetSpriteCursor() +{ + return sprite.current; +} + +void +GetSpritePosition(int *px, int *py) +{ + *px = sprite.hotPhys.x; + *py = sprite.hotPhys.y; +} + +#ifdef PANORAMIX +int +XineramaGetCursorScreen() +{ + if(!noPanoramiXExtension) { + return sprite.screen->myNum; + } else { + return 0; + } +} +#endif /* PANORAMIX */ + +#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ + +static void +MonthChangedOrBadTime(register xEvent *xE) +{ + /* If the ddx/OS is careless about not processing timestamped events from + * different sources in sorted order, then it's possible for time to go + * backwards when it should not. Here we ensure a decent time. + */ + if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) + currentTime.months++; + else + XE_KBPTR.time = currentTime.milliseconds; +} + +#define NoticeTime(xE) { \ + if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ + MonthChangedOrBadTime(xE); \ + currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ + lastDeviceEventTime = currentTime; } + +void +NoticeEventTime(register xEvent *xE) +{ + if (!syncEvents.playingEvents) + NoticeTime(xE); +} + +/************************************************************************** + * The following procedures deal with synchronous events * + **************************************************************************/ + +void +EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) +{ + register QdEventPtr tail = *syncEvents.pendtail; + register QdEventPtr qe; + xEvent *qxE; + + NoticeTime(xE); + +#ifdef XKB + /* Fix for key repeating bug. */ + if (device->key != NULL && device->key->xkbInfo != NULL && + xE->u.u.type == KeyRelease) + AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); +#endif + + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* The RECORD spec says that the root window field of motion events + * must be valid. At this point, it hasn't been filled in yet, so + * we do it here. The long expression below is necessary to get + * the current root window; the apparently reasonable alternative + * GetCurrentRootWindow()->drawable.id doesn't give you the right + * answer on the first motion event after a screen change because + * the data that GetCurrentRootWindow relies on hasn't been + * updated yet. + */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + if (xE->u.u.type == MotionNotify) + { +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + panoramiXdataPtr[0].x; + XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + panoramiXdataPtr[0].y; + } +#endif + sprite.hotPhys.x = XE_KBPTR.rootX; + sprite.hotPhys.y = XE_KBPTR.rootY; + /* do motion compression */ + if (tail && + (tail->event->u.u.type == MotionNotify) && + (tail->pScreen == sprite.hotPhys.pScreen)) + { + tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; + tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.time = XE_KBPTR.time; + tail->months = currentTime.months; + return; + } + } + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + if (!qe) + return; + qe->next = (QdEventPtr)NULL; + qe->device = device; + qe->pScreen = sprite.hotPhys.pScreen; + qe->months = currentTime.months; + qe->event = (xEvent *)(qe + 1); + qe->evcount = count; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + *qxE = *xE; + if (tail) + syncEvents.pendtail = &tail->next; + *syncEvents.pendtail = qe; +} + +static void +PlayReleasedEvents(void) +{ + register QdEventPtr *prev, qe; + register DeviceIntPtr dev; + + prev = &syncEvents.pending; + while ( (qe = *prev) ) + { + if (!qe->device->sync.frozen) + { + *prev = qe->next; + if (*syncEvents.pendtail == *prev) + syncEvents.pendtail = prev; + if (qe->event->u.u.type == MotionNotify) + CheckVirtualMotion(qe, NullWindow); + syncEvents.time.months = qe->months; + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer */ + if(!noPanoramiXExtension) { + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y; + } +#endif + (*qe->device->public.processInputProc)(qe->event, qe->device, + qe->evcount); + xfree(qe); + for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + ; + if (!dev) + break; + /* Playing the event may have unfrozen another device. */ + /* So to play it safe, restart at the head of the queue */ + prev = &syncEvents.pending; + } + else + prev = &qe->next; + } +} + +static void +FreezeThaw(register DeviceIntPtr dev, Bool frozen) +{ + dev->sync.frozen = frozen; + if (frozen) + dev->public.processInputProc = dev->public.enqueueInputProc; + else + dev->public.processInputProc = dev->public.realInputProc; +} + +void +ComputeFreezes() +{ + register DeviceIntPtr replayDev = syncEvents.replayDev; + register int i; + WindowPtr w; + register xEvent *xE; + int count; + GrabPtr grab; + register DeviceIntPtr dev; + + for (dev = inputInfo.devices; dev; dev = dev->next) + FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) + return; + syncEvents.playingEvents = TRUE; + if (replayDev) + { + xE = replayDev->sync.event; + count = replayDev->sync.evcount; + syncEvents.replayDev = (DeviceIntPtr)NULL; + + w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < spriteTraceGood; i++) + { + if (syncEvents.replayWin == spriteTrace[i]) + { + if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, + replayDev, count); + } + goto playmore; + } + } + /* must not still be in the same stack */ + if (replayDev->focus) + DeliverFocusedEvent(replayDev, xE, w, count); + else + DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); + } +playmore: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->sync.frozen) + { + PlayReleasedEvents(); + break; + } + } + syncEvents.playingEvents = FALSE; + /* the following may have been skipped during replay, so do it now */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(); +} + +#ifdef RANDR +void +ScreenRestructured (ScreenPtr pScreen) +{ + GrabPtr grab; + + if ((grab = inputInfo.pointer->grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) +{ + register GrabPtr grab = thisDev->grab; + register DeviceIntPtr dev; + + if (thisMode == GrabModeSync) + thisDev->sync.state = FROZEN_NO_EVENT; + else + { /* free both if same client owns both */ + thisDev->sync.state = THAWED; + if (thisDev->sync.other && + (CLIENT_BITS(thisDev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + thisDev->sync.other = NullGrab; + } + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev != thisDev) + { + if (otherMode == GrabModeSync) + dev->sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->sync.other && + (CLIENT_BITS(dev->sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->sync.other = NullGrab; + } + } + } + ComputeFreezes(); +} + +void +ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab, + TimeStamp time, Bool autoGrab) +{ + WindowPtr oldWin = (mouse->grab) ? mouse->grab->window + : sprite.win; + + if (grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + } + DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + mouse->valuator->motionHintWindow = NullWindow; + if (syncEvents.playingEvents) + mouse->grabTime = syncEvents.time; + else + mouse->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; + mouse->activeGrab = *grab; + mouse->grab = &mouse->activeGrab; + mouse->fromPassiveGrab = autoGrab; + PostNewCursor(); + CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); +} + +void +DeactivatePointerGrab(register DeviceIntPtr mouse) +{ + register GrabPtr grab = mouse->grab; + register DeviceIntPtr dev; + + mouse->valuator->motionHintWindow = NullWindow; + mouse->grab = NullGrab; + mouse->sync.state = NOT_GRABBED; + mouse->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + if (grab->confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + PostNewCursor(); + if (grab->cursor) + FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); +} + +void +ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) +{ + WindowPtr oldWin; + + if (keybd->grab) + oldWin = keybd->grab->window; + else if (keybd->focus) + oldWin = keybd->focus->win; + else + oldWin = sprite.win; + if (oldWin == FollowKeyboardWin) + oldWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); + if (syncEvents.playingEvents) + keybd->grabTime = syncEvents.time; + else + keybd->grabTime = time; + keybd->activeGrab = *grab; + keybd->grab = &keybd->activeGrab; + keybd->fromPassiveGrab = passive; + CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); +} + +void +DeactivateKeyboardGrab(register DeviceIntPtr keybd) +{ + register GrabPtr grab = keybd->grab; + register DeviceIntPtr dev; + register WindowPtr focusWin = keybd->focus ? keybd->focus->win + : sprite.win; + + if (focusWin == FollowKeyboardWin) + focusWin = inputInfo.keyboard->focus->win; + if (keybd->valuator) + keybd->valuator->motionHintWindow = NullWindow; + keybd->grab = NullGrab; + keybd->sync.state = NOT_GRABBED; + keybd->fromPassiveGrab = FALSE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->sync.other == grab) + dev->sync.other = NullGrab; + } + DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); +} + +void +AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) +{ + Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; + TimeStamp grabTime; + register DeviceIntPtr dev; + + thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisSynced = FALSE; + otherGrabbed = FALSE; + othersFrozen = TRUE; + grabTime = thisDev->grabTime; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + { + if (!(thisGrabbed || otherGrabbed) || + (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) + grabTime = dev->grabTime; + otherGrabbed = TRUE; + if (thisDev->sync.other == dev->grab) + thisSynced = TRUE; + if (dev->sync.state < FROZEN) + othersFrozen = FALSE; + } + else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + othersFrozen = FALSE; + } + if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + return; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, grabTime) == EARLIER)) + return; + switch (newState) + { + case THAWED: /* Async */ + if (thisGrabbed) + thisDev->sync.state = THAWED; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + break; + case FREEZE_NEXT_EVENT: /* Sync */ + if (thisGrabbed) + { + thisDev->sync.state = FREEZE_NEXT_EVENT; + if (thisSynced) + thisDev->sync.other = NullGrab; + ComputeFreezes(); + } + break; + case THAWED_BOTH: /* AsyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + case NOT_GRABBED: /* Replay */ + if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + { + if (thisSynced) + thisDev->sync.other = NullGrab; + syncEvents.replayDev = thisDev; + syncEvents.replayWin = thisDev->grab->window; + (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayDev = (DeviceIntPtr)NULL; + } + break; + case THAW_OTHERS: /* AsyncOthers */ + if (othersFrozen) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + if (dev->grab && SameClient(dev->grab, client)) + dev->sync.state = THAWED; + if (dev->sync.other && SameClient(dev->sync.other, client)) + dev->sync.other = NullGrab; + } + ComputeFreezes(); + } + break; + } +} + +int +ProcAllowEvents(register ClientPtr client) +{ + TimeStamp time; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + REQUEST(xAllowEventsReq); + + REQUEST_SIZE_MATCH(xAllowEventsReq); + time = ClientTimeToServerTime(stuff->time); + switch (stuff->mode) + { + case ReplayPointer: + AllowSome(client, time, mouse, NOT_GRABBED); + break; + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + break; + case AsyncPointer: + AllowSome(client, time, mouse, THAWED); + break; + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED); + break; + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + break; + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED); + break; + case SyncBoth: + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + break; + case AsyncBoth: + AllowSome(client, time, keybd, THAWED_BOTH); + break; + default: + client->errorValue = stuff->mode; + return BadValue; + } + return Success; +} + +void +ReleaseActiveGrabs(ClientPtr client) +{ + register DeviceIntPtr dev; + Bool done; + + /* XXX CloseDownClient should remove passive grabs before + * releasing active grabs. + */ + do { + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->grab && SameClient(dev->grab, client)) + { + (*dev->DeactivateGrab)(dev); + done = FALSE; + } + } + } while (!done); +} + +/************************************************************************** + * The following procedures deal with delivering events * + **************************************************************************/ + +int +TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, + Mask filter, GrabPtr grab) +{ + int i; + int type; + +#ifdef DEBUG + if (debug_events) ErrorF( + "Event([%d, %d], mask=0x%x), client=%d", + pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); +#endif + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) + return -1; /* don't send, but notify caller */ + type = pEvents->u.u.type; + if (type == MotionNotify) + { + if (mask & PointerMotionHintMask) + { + if (WID(inputInfo.pointer->valuator->motionHintWindow) == + pEvents->u.keyButtonPointer.event) + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); + fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n"); +#endif + return 1; /* don't send, but pretend we did */ + } + pEvents->u.u.detail = NotifyHint; + } + else + { + pEvents->u.u.detail = NotifyNormal; + } + } +#ifdef XINPUT + else + { + if ((type == DeviceMotionNotify) && + MaybeSendDeviceMotionNotifyHint + ((deviceKeyButtonPointer*)pEvents, mask) != 0) + return 1; + } +#endif + type &= 0177; + if (type != KeymapNotify) + { + /* all extension events must have a sequence number */ + for (i = 0; i < count; i++) + pEvents[i].u.u.sequenceNumber = client->sequence; + } + + if (BitIsOn(criticalEvents, type)) + { +#ifdef SMART_SCHEDULE + if (client->smart_priority < SMART_MAX_PRIORITY) + client->smart_priority++; +#endif + SetCriticalOutputPending(); + } + + WriteEventsToClient(client, count, pEvents); +#ifdef DEBUG + if (debug_events) ErrorF( " delivered\n"); +#endif + return 1; + } + else + { +#ifdef DEBUG + if (debug_events) ErrorF("\n"); +#endif + return 0; + } +} + +int +DeliverEventsToWindow(register WindowPtr pWin, xEvent *pEvents, int count, + Mask filter, GrabPtr grab, int mskidx) +{ + int deliveries = 0, nondeliveries = 0; + int attempt; + register InputClients *other; + ClientPtr client = NullClient; + Mask deliveryMask = 0; /* If a grab occurs due to a button press, then + this mask is the mask of the grab. */ + int type = pEvents->u.u.type; + + /* CantBeFiltered means only window owner gets the event */ + if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + { + /* if nobody ever wants to see this event, skip some work */ + if (filter != CantBeFiltered && + !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) + return 0; + if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = wClient(pWin); + deliveryMask = pWin->eventMask; + } else + nondeliveries--; + } + } + if (filter != CantBeFiltered) + { + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + if ( (attempt = TryClientEvents(rClient(other), pEvents, count, + other->mask[mskidx], filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } + if ((type == ButtonPress) && deliveries && (!grab)) + { + GrabRec tempGrab; + + tempGrab.device = inputInfo.pointer; + tempGrab.resource = client->clientAsMask; + tempGrab.window = pWin; + tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; + tempGrab.eventMask = deliveryMask; + tempGrab.keyboardMode = GrabModeAsync; + tempGrab.pointerMode = GrabModeAsync; + tempGrab.confineTo = NullWindow; + tempGrab.cursor = NullCursor; + (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, + currentTime, TRUE); + } + else if ((type == MotionNotify) && deliveries) + inputInfo.pointer->valuator->motionHintWindow = pWin; +#ifdef XINPUT + else + { + if (((type == DeviceMotionNotify) +#ifdef XKB + || (type == DeviceButtonPress) +#endif + ) && deliveries) + CheckDeviceGrabAndHintWindow (pWin, type, + (deviceKeyButtonPointer*) pEvents, + grab, client, deliveryMask); + } +#endif + if (deliveries) + return deliveries; + return nondeliveries; +} + +/* If the event goes to dontClient, don't send it and return 0. if + send works, return 1 or if send didn't work, return 2. + Only works for core events. +*/ + +#ifdef PANORAMIX +static int +XineramaTryClientEventsResult( + ClientPtr client, + GrabPtr grab, + Mask mask, + Mask filter +){ + if ((client) && (client != serverClient) && (!client->clientGone) && + ((filter == CantBeFiltered) || (mask & filter))) + { + if (grab && !SameClient(grab, client)) return -1; + else return 1; + } + return 0; +} +#endif + +int +MaybeDeliverEventsToClient(register WindowPtr pWin, xEvent *pEvents, + int count, Mask filter, ClientPtr dontClient) +{ + register OtherClients *other; + + + if (pWin->eventMask & filter) + { + if (wClient(pWin) == dontClient) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + wClient(pWin), NullGrab, pWin->eventMask, filter); +#endif + return TryClientEvents(wClient(pWin), pEvents, count, + pWin->eventMask, filter, NullGrab); + } + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->mask & filter) + { + if (SameClient(other, dontClient)) + return 0; +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return XineramaTryClientEventsResult( + rClient(other), NullGrab, other->mask, filter); +#endif + return TryClientEvents(rClient(other), pEvents, count, + other->mask, filter, NullGrab); + } + } + return 2; +} + +static void +FixUpEventFromWindow( + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild) +{ + if (calcChild) + { + WindowPtr w=spriteTrace[spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls + this function with child == None anyway. */ + + while (w) + { + /* If the source window is same as event window, child should be + none. Don't bother going all all the way back to the root. */ + + if (w == pWin) + { + child = None; + break; + } + + if (w->parent == pWin) + { + child = w->drawable.id; + break; + } + w = w->parent; + } + } + XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.event = pWin->drawable.id; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + XE_KBPTR.sameScreen = xTrue; + XE_KBPTR.child = child; + XE_KBPTR.eventX = + XE_KBPTR.rootX - pWin->drawable.x; + XE_KBPTR.eventY = + XE_KBPTR.rootY - pWin->drawable.y; + } + else + { + XE_KBPTR.sameScreen = xFalse; + XE_KBPTR.child = None; + XE_KBPTR.eventX = 0; + XE_KBPTR.eventY = 0; + } +} + +int +DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab, + register WindowPtr stopAt, DeviceIntPtr dev, int count) +{ + Window child = None; + int type = xE->u.u.type; + Mask filter = filters[type]; + int deliveries = 0; + + if (type & EXTENSION_EVENT_BASE) + { + register OtherInputMasks *inputMasks; + int mskidx = dev->id; + + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) + return 0; + while (pWin) + { + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, mskidx); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + if (pWin) + inputMasks = wOtherInputMasks(pWin); + } + } + else + { + if (!(filter & pWin->deliverableEvents)) + return 0; + while (pWin) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(pWin, xE, count, filter, + grab, 0); + if (deliveries > 0) + return deliveries; + } + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + child = pWin->drawable.id; + pWin = pWin->parent; + } + } + return 0; +} + +/* not useful for events that propagate up the tree or extension events */ +int +DeliverEvents(register WindowPtr pWin, register xEvent *xE, int count, + register WindowPtr otherParent) +{ + Mask filter; + int deliveries; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + return count; +#endif + + if (!count) + return 0; + filter = filters[xE->u.u.type]; + if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) + xE->u.destroyNotify.event = pWin->drawable.id; + if (filter != StructureAndSubMask) + return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + NullGrab, 0); + if (pWin->parent) + { + xE->u.destroyNotify.event = pWin->parent->drawable.id; + deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + SubstructureNotifyMask, NullGrab, + 0); + if (xE->u.u.type == ReparentNotify) + { + xE->u.destroyNotify.event = otherParent->drawable.id; + deliveries += DeliverEventsToWindow(otherParent, xE, count, + SubstructureNotifyMask, + NullGrab, 0); + } + } + return deliveries; +} + + +static Bool +PointInBorderSize(WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(POINT_IN_REGION(sprite.screen, + &sprite.windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + &box)) + return TRUE; + } + } +#endif + return FALSE; +} + +static WindowPtr +XYToWindow(int x, int y) +{ + register WindowPtr pWin; + BoxRec box; + + spriteTraceGood = 1; /* root window still there */ + pWin = ROOT->firstChild; + while (pWin) + { + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth(pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) +#ifdef SHAPE + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) +#endif + ) + { + if (spriteTraceGood >= spriteTraceSize) + { + spriteTraceSize += 10; + Must_have_memory = TRUE; /* XXX */ + spriteTrace = (WindowPtr *)xrealloc( + spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + spriteTrace[spriteTraceGood++] = pWin; + pWin = pWin->firstChild; + } + else + pWin = pWin->nextSib; + } + return spriteTrace[spriteTraceGood-1]; +} + +static Bool +CheckMotion(xEvent *xE) +{ + WindowPtr prevSpriteWin = sprite.win; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaCheckMotion(xE); +#endif + + if (xE && !syncEvents.playingEvents) + { + if (sprite.hot.pScreen != sprite.hotPhys.pScreen) + { + sprite.hot.pScreen = sprite.hotPhys.pScreen; + ROOT = WindowTable[sprite.hot.pScreen->myNum]; + } +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = XE_KBPTR.rootX; +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = XE_KBPTR.rootY; + if (sprite.hot.x < sprite.physLimits.x1) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x1; + else if (sprite.hot.x >= sprite.physLimits.x2) +#ifdef XEVIE + xeviehot.x = +#endif + sprite.hot.x = sprite.physLimits.x2 - 1; + if (sprite.hot.y < sprite.physLimits.y1) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y1; + else if (sprite.hot.y >= sprite.physLimits.y2) +#ifdef XEVIE + xeviehot.y = +#endif + sprite.hot.y = sprite.physLimits.y2 - 1; +#ifdef SHAPE + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); +#endif + sprite.hotPhys = sprite.hot; + if ((sprite.hotPhys.x != XE_KBPTR.rootX) || + (sprite.hotPhys.y != XE_KBPTR.rootY)) + { + (*sprite.hotPhys.pScreen->SetCursorPosition)( + sprite.hotPhys.pScreen, + sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + } + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + } + +#ifdef XEVIE + xeviewin = +#endif + sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); +#ifdef notyet + if (!(sprite.win->deliverableEvents & + Motion_Filter(inputInfo.pointer->button)) + !syncEvents.playingEvents) + { + /* XXX Do PointerNonInterestBox here */ + } +#endif + if (sprite.win != prevSpriteWin) + { + if (prevSpriteWin != NullWindow) { + if (!xE) + UpdateCurrentTimeIf(); + DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); + } + PostNewCursor(); + return FALSE; + } + return TRUE; +} + +void +WindowsRestructured() +{ + (void) CheckMotion((xEvent *)NULL); +} + +#ifdef PANORAMIX +/* This was added to support reconfiguration under Xdmx. The problem is + * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin + * other than 0,0, the information in the private sprite structure must + * be updated accordingly, or XYToWindow (and other routines) will not + * compute correctly. */ +void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) +{ + ScreenPtr pScreen = win->drawable.pScreen; + GrabPtr grab; + + if (noPanoramiXExtension) return; + + sprite.hot.x -= xoff; + sprite.hot.y -= yoff; + + sprite.hotPhys.x -= xoff; + sprite.hotPhys.y -= yoff; + + sprite.hotLimits.x1 -= xoff; + sprite.hotLimits.y1 -= yoff; + sprite.hotLimits.x2 -= xoff; + sprite.hotLimits.y2 -= yoff; + + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff); + if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2)) + REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff); + + /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ + if ((grab = inputInfo.pointer->grab) && grab->confineTo) { + if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) + sprite.hotPhys.x = sprite.hotPhys.y = 0; + ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + } else + ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], + TRUE, FALSE); +} +#endif + +void +DefineInitialRootWindow(register WindowPtr win) +{ + register ScreenPtr pScreen = win->drawable.pScreen; + + sprite.hotPhys.pScreen = pScreen; + sprite.hotPhys.x = pScreen->width / 2; + sprite.hotPhys.y = pScreen->height / 2; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = win; + sprite.current = wCursor (win); + sprite.current->refcnt++; + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) ( + pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.confineWin = NullWindow; +#ifdef SHAPE + sprite.hotShape = NullRegion; +#endif + sprite.screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_NULL(pScreen, &sprite.Reg1); + REGION_NULL(pScreen, &sprite.Reg2); + } +#endif +} + +/* + * This does not take any shortcuts, and even ignores its argument, since + * it does not happen very often, and one has to walk up the tree since + * this might be a newly instantiated cursor for an intermediate window + * between the one the pointer is in and the one that the last cursor was + * instantiated from. + */ +void +WindowHasNewCursor(WindowPtr pWin) +{ + PostNewCursor(); +} + +void +NewCurrentScreen(ScreenPtr newScreen, int x, int y) +{ + sprite.hotPhys.x = x; + sprite.hotPhys.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + panoramiXdataPtr[0].x; + sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + panoramiXdataPtr[0].y; + if (newScreen != sprite.screen) { + sprite.screen = newScreen; + /* Make sure we tell the DDX to update its copy of the screen */ + if(sprite.confineWin) + XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + else + XineramaConfineCursorToWindow(WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get + told of the pointer warp so we reposition it here */ + if(!syncEvents.playingEvents) + (*sprite.screen->SetCursorPosition)(sprite.screen, + sprite.hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[sprite.screen->myNum].x, + sprite.hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + } + } else +#endif + if (newScreen != sprite.hotPhys.pScreen) + ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); +} + +#ifdef PANORAMIX + +static Bool +XineramaPointInWindowIsVisible( + WindowPtr pWin, + int x, + int y +) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + int i, xoff, yoff; + + if (!pWin->realized) return FALSE; + + if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) + return TRUE; + + if(!XineramaSetWindowPntrs(pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; + + for(i = 1; i < PanoramiXNumScreens; i++) { + pWin = sprite.windows[i]; + pScreen = pWin->drawable.pScreen; + x = xoff - panoramiXdataPtr[i].x; + y = yoff - panoramiXdataPtr[i].y; + + if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return TRUE; + + } + + return FALSE; +} + +static int +XineramaWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + + REQUEST(xWarpPointerReq); + + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if(source == WindowTable[0]) { + winX -= panoramiXdataPtr[0].x; + winY -= panoramiXdataPtr[0].y; + } + if (x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !XineramaPointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) { + x = dest->drawable.x; + y = dest->drawable.y; + if(dest == WindowTable[0]) { + x -= panoramiXdataPtr[0].x; + y -= panoramiXdataPtr[0].y; + } + } + + x += stuff->dstX; + y += stuff->dstY; + + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); + + XineramaSetCursorPosition(x, y, TRUE); + + return Success; +} + +#endif + + +int +ProcWarpPointer(ClientPtr client) +{ + WindowPtr dest = NULL; + int x, y; + ScreenPtr newScreen; + + REQUEST(xWarpPointerReq); + + REQUEST_SIZE_MATCH(xWarpPointerReq); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return XineramaWarpPointer(client); +#endif + + if (stuff->dstWid != None) + { + dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess); + if (!dest) + return BadWindow; + } + x = sprite.hotPhys.x; + y = sprite.hotPhys.y; + + if (stuff->srcWid != None) + { + int winX, winY; + XID winID = stuff->srcWid; + WindowPtr source; + + source = SecurityLookupWindow(winID, client, SecurityReadAccess); + if (!source) return BadWindow; + + winX = source->drawable.x; + winY = source->drawable.y; + if (source->drawable.pScreen != sprite.hotPhys.pScreen || + x < winX + stuff->srcX || + y < winY + stuff->srcY || + (stuff->srcWidth != 0 && + winX + stuff->srcX + (int)stuff->srcWidth < x) || + (stuff->srcHeight != 0 && + winY + stuff->srcY + (int)stuff->srcHeight < y) || + !PointInWindowIsVisible(source, x, y)) + return Success; + } + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = sprite.hotPhys.pScreen; + + x += stuff->dstX; + y += stuff->dstY; + + if (x < 0) + x = 0; + else if (x >= newScreen->width) + x = newScreen->width - 1; + if (y < 0) + y = 0; + else if (y >= newScreen->height) + y = newScreen->height - 1; + + if (newScreen == sprite.hotPhys.pScreen) + { + if (x < sprite.physLimits.x1) + x = sprite.physLimits.x1; + else if (x >= sprite.physLimits.x2) + x = sprite.physLimits.x2 - 1; + if (y < sprite.physLimits.y1) + y = sprite.physLimits.y1; + else if (y >= sprite.physLimits.y2) + y = sprite.physLimits.y2 - 1; +#if defined(SHAPE) + if (sprite.hotShape) + ConfineToShape(sprite.hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + } + else if (!PointerConfinedToScreen()) + { + NewCurrentScreen(newScreen, x, y); + } + return Success; +} + +static Bool +BorderSizeNotEmpty(WindowPtr pWin) +{ + if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + return TRUE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + int i; + + for(i = 1; i < PanoramiXNumScreens; i++) { + if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + return TRUE; + } + } +#endif + return FALSE; +} + +/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a + passive grab set on the window to be activated. */ + +static Bool +CheckPassiveGrabsOnWindow( + WindowPtr pWin, + register DeviceIntPtr device, + register xEvent *xE, + int count) +{ + register GrabPtr grab = wPassiveGrabs(pWin); + GrabRec tempGrab; + register xEvent *dxE; + + if (!grab) + return FALSE; + tempGrab.window = pWin; + tempGrab.device = device; + tempGrab.type = xE->u.u.type; + tempGrab.detail.exact = xE->u.u.detail; + tempGrab.detail.pMask = NULL; + tempGrab.modifiersDetail.pMask = NULL; + for (; grab; grab = grab->next) + { +#ifdef XKB + DeviceIntPtr gdev; + XkbSrvInfoPtr xkbi; + + gdev= grab->modifierDevice; + xkbi= gdev->key->xkbInfo; +#endif + tempGrab.modifierDevice = grab->modifierDevice; + if ((device == grab->modifierDevice) && + ((xE->u.u.type == KeyPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceKeyPress) +#endif + )) + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); +#else + grab->modifierDevice->key->prev_state; +#endif + else + tempGrab.modifiersDetail.exact = +#ifdef XKB + (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); +#else + grab->modifierDevice->key->state; +#endif + if (GrabMatchesSecond(&tempGrab, grab) && + (!grab->confineTo || + (grab->confineTo->realized && + BorderSizeNotEmpty(grab->confineTo)))) + { +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE)) + return FALSE; +#endif +#ifdef XKB + if (!noXkbExtension) { + XE_KBPTR.state &= 0x1f00; + XE_KBPTR.state |= + tempGrab.modifiersDetail.exact&(~0x1f00); + } +#endif + (*device->ActivateGrab)(device, grab, currentTime, TRUE); + + FixUpEventFromWindow(xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), xE, count, + filters[xE->u.u.type], + filters[xE->u.u.type], grab); + + if (device->sync.state == FROZEN_NO_EVENT) + { + if (device->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + device->sync.event = (xEvent *)xrealloc(device->sync.event, + count* + sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + device->sync.evcount = count; + for (dxE = device->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + device->sync.state = FROZEN_WITH_EVENT; + } + return TRUE; + } + } + return FALSE; +} + +/** +"CheckDeviceGrabs" handles both keyboard and pointer events that may cause +a passive grab to be activated. If the event is a keyboard event, the +ancestors of the focus window are traced down and tried to see if they have +any passive grabs to be activated. If the focus window itself is reached and +it's descendants contain they pointer, the ancestors of the window that the +pointer is in are then traced down starting at the focus window, otherwise no +grabs are activated. If the event is a pointer event, the ancestors of the +window that the pointer is in are traced down starting at the root until +CheckPassiveGrabs causes a passive grab to activate or all the windows are +tried. PRH +*/ + +Bool +CheckDeviceGrabs(register DeviceIntPtr device, register xEvent *xE, + int checkFirst, int count) +{ + register int i; + register WindowPtr pWin = NULL; + register FocusClassPtr focus = device->focus; + + if (((xE->u.u.type == ButtonPress) +#if defined(XINPUT) && defined(XKB) + || (xE->u.u.type == DeviceButtonPress) +#endif + ) && (device->button->buttonsDown != 1)) + return FALSE; + + i = checkFirst; + + if (focus) + { + for (; i < focus->traceGood; i++) + { + pWin = focus->trace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + if ((focus->win == NoneWin) || + (i >= spriteTraceGood) || + ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + return FALSE; + } + + for (; i < spriteTraceGood; i++) + { + pWin = spriteTrace[i]; + if (pWin->optional && + CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + return TRUE; + } + + return FALSE; +} + +void +DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) +{ + WindowPtr focus = keybd->focus->win; + int mskidx = 0; + + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + if (!focus) + return; + if (focus == PointerRootWin) + { + DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); + return; + } + if ((focus == window) || IsParent(focus, window)) + { + if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) + return; + } + /* just deliver it to the focus window */ + FixUpEventFromWindow(xE, focus, None, FALSE); + if (xE->u.u.type & EXTENSION_EVENT_BASE) + mskidx = keybd->id; + (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], + NullGrab, mskidx); +} + +void +DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev, + Bool deactivateGrab, int count) +{ + register GrabPtr grab = thisDev->grab; + int deliveries = 0; + register DeviceIntPtr dev; + register xEvent *dxE; + + if (grab->ownerEvents) + { + WindowPtr focus; + + if (thisDev->focus) + { + focus = thisDev->focus->win; + if (focus == FollowKeyboardWin) + focus = inputInfo.keyboard->focus->win; + } + else + focus = PointerRootWin; + if (focus == PointerRootWin) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, + thisDev, count); + else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) + deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + thisDev, count); + else if (focus) + deliveries = DeliverDeviceEvents(focus, xE, grab, focus, + thisDev, count); + } + if (!deliveries) + { + FixUpEventFromWindow(xE, grab->window, None, TRUE); + deliveries = TryClientEvents(rClient(grab), xE, count, + (Mask)grab->eventMask, + filters[xE->u.u.type], grab); + if (deliveries && (xE->u.u.type == MotionNotify +#ifdef XINPUT + || xE->u.u.type == DeviceMotionNotify +#endif + )) + thisDev->valuator->motionHintWindow = grab->window; + } + if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify +#ifdef XINPUT + && xE->u.u.type != DeviceMotionNotify +#endif + )) + switch (thisDev->sync.state) + { + case FREEZE_BOTH_NEXT_EVENT: + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev == thisDev) + continue; + FreezeThaw(dev, TRUE); + if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(dev->grab->resource) == + CLIENT_BITS(thisDev->grab->resource))) + dev->sync.state = FROZEN_NO_EVENT; + else + dev->sync.other = thisDev->grab; + } + /* fall through */ + case FREEZE_NEXT_EVENT: + thisDev->sync.state = FROZEN_WITH_EVENT; + FreezeThaw(thisDev, TRUE); + if (thisDev->sync.evcount < count) + { + Must_have_memory = TRUE; /* XXX */ + thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + count*sizeof(xEvent)); + Must_have_memory = FALSE; /* XXX */ + } + thisDev->sync.evcount = count; + for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + *dxE = *xE; + break; + } +} + +void +#ifdef XKB +CoreProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#else +ProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count) +#endif +{ + int key, bit; + register BYTE *kptr; + register int i; + register CARD8 modifiers; + register CARD16 mask; + GrabPtr grab = keybd->grab; + Bool deactivateGrab = FALSE; + register KeyClassPtr keyc = keybd->key; +#ifdef XEVIE + static Window rootWin = 0; + + if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + if((xE->u.u.type == KeyPress && (*kptr & bit)) || + (xE->u.u.type == KeyRelease && !(*kptr & bit))) + {} else { +#ifdef XKB + if(!noXkbExtension) + xevieKBEventSent = 1; +#endif + if(!xevieKBEventSent) + { + xeviekb = keybd; + if(!rootWin) { + rootWin = GetCurrentRootWindow()->drawable.id; + } + xE->u.keyButtonPointer.event = xeviewin->drawable.id; + xE->u.keyButtonPointer.root = rootWin; + xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild-> +drawable.id:0; + xE->u.keyButtonPointer.rootX = xeviehot.x; + xE->u.keyButtonPointer.rootY = xeviehot.y; + xE->u.keyButtonPointer.state = keyc->state; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); +#ifdef XKB + if(noXkbExtension) +#endif + return; + } else { + xevieKBEventSent = 0; + } + } + } +#endif + + if (!syncEvents.playingEvents) + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } +#ifdef XEVIE + /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */ + if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type] +#ifdef XKB + && !noXkbExtension +#endif + ))) +#endif + XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + modifiers = keyc->modifierMap[key]; +#if defined(XKB) && defined(XEVIE) + if(!noXkbExtension && !xeviegrabState && + xevieFlag && clients[xevieClientIndex] && + (xevieMask & xevieFilters[xE->u.u.type])) { + switch(xE->u.u.type) { + case KeyPress: *kptr &= ~bit; break; + case KeyRelease: *kptr |= bit; break; + } + } +#endif + +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("CoreProcessKbdEvent: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + if (*kptr & bit) /* allow ddx to generate multiple downs */ + { + if (!modifiers) + { + xE->u.u.type = KeyRelease; + (*keybd->public.processInputProc)(xE, keybd, count); + xE->u.u.type = KeyPress; + /* release can have side effects, don't fall through */ + (*keybd->public.processInputProc)(xE, keybd, count); + } + return; + } + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr |= bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) + { + /* This key affects modifier "i" */ + keyc->modifierKeyCount[i]++; + keyc->state |= mask; + modifiers &= ~mask; + } + } + if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) + { + keybd->activatingKey = key; + return; + } + break; + case KeyRelease: + if (!(*kptr & bit)) /* guard against duplicates */ + return; + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + *kptr &= ~bit; + keyc->prev_state = keyc->state; + for (i = 0, mask = 1; modifiers; i++, mask <<= 1) + { + if (mask & modifiers) { + /* This key affects modifier "i" */ + if (--keyc->modifierKeyCount[i] <= 0) { + keyc->state &= ~mask; + keyc->modifierKeyCount[i] = 0; + } + modifiers &= ~mask; + } + } + if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + deactivateGrab = TRUE; + break; + default: + FatalError("Impossible keyboard event"); + } + if (grab) + DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); + else + DeliverFocusedEvent(keybd, xE, sprite.win, count); + if (deactivateGrab) + (*keybd->DeactivateGrab)(keybd); +} + +#ifdef XKB +/* This function is used to set the key pressed or key released state - + this is only used when the pressing of keys does not cause + CoreProcessKeyEvent to be called, as in for example Mouse Keys. +*/ +void +FixKeyState (register xEvent *xE, register DeviceIntPtr keybd) +{ + int key, bit; + register BYTE *kptr; + register KeyClassPtr keyc = keybd->key; + + key = xE->u.u.detail; + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); +#ifdef DEBUG + if ((xkbDebugFlags&0x4)&& + ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) { + ErrorF("FixKeyState: Key %d %s\n",key, + (xE->u.u.type==KeyPress?"down":"up")); + } +#endif + switch (xE->u.u.type) + { + case KeyPress: + *kptr |= bit; + break; + case KeyRelease: + *kptr &= ~bit; + break; + default: + FatalError("Impossible keyboard event"); + } +} +#endif + +void +#ifdef XKB +CoreProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#else +ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count) +#endif +{ + register GrabPtr grab = mouse->grab; + Bool deactivateGrab = FALSE; + register ButtonClassPtr butc = mouse->button; +#ifdef XKB + XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; +#endif +#ifdef XEVIE + if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && + (xevieMask & xevieFilters[xE->u.u.type])) { + if(xevieEventSent) + xevieEventSent = 0; + else { + xeviemouse = mouse; + WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); + return; + } + } +#endif + + if (!syncEvents.playingEvents) + NoticeTime(xE) + XE_KBPTR.state = (butc->state | ( +#ifdef XKB + (noXkbExtension ? + inputInfo.keyboard->key->state : + xkbi->state.grab_mods) +#else + inputInfo.keyboard->key->state +#endif + )); + { + NoticeTime(xE); + if (DeviceEventCallback) + { + DeviceEventInfoRec eventinfo; + /* see comment in EnqueueEvents regarding the next three lines */ + if (xE->u.u.type == MotionNotify) + XE_KBPTR.root = + WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + eventinfo.events = xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); + } + } + if (xE->u.u.type != MotionNotify) + { + register int key; + register BYTE *kptr; + int bit; + + XE_KBPTR.rootX = sprite.hot.x; + XE_KBPTR.rootY = sprite.hot.y; + + key = xE->u.u.detail; + kptr = &butc->down[key >> 3]; + bit = 1 << (key & 7); + switch (xE->u.u.type) + { + case ButtonPress: + mouse->valuator->motionHintWindow = NullWindow; + if (!(*kptr & bit)) + butc->buttonsDown++; + butc->motionMask = ButtonMotionMask; + *kptr |= bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state |= (Button1Mask >> 1) << xE->u.u.detail; + filters[MotionNotify] = Motion_Filter(butc); + if (!grab) + if (CheckDeviceGrabs(mouse, xE, 0, count)) + return; + break; + case ButtonRelease: + mouse->valuator->motionHintWindow = NullWindow; + if (*kptr & bit) + --butc->buttonsDown; + if (!butc->buttonsDown) + butc->motionMask = 0; + *kptr &= ~bit; +#if !defined(XFree86Server) || !defined(XINPUT) + xE->u.u.detail = butc->map[key]; +#endif + if (xE->u.u.detail == 0) + return; + if (xE->u.u.detail <= 5) + butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); + filters[MotionNotify] = Motion_Filter(butc); + if (!butc->state && mouse->fromPassiveGrab) + deactivateGrab = TRUE; + break; + default: + FatalError("bogus pointer event from ddx"); + } + } + else if (!CheckMotion(xE)) + return; + if (grab) + DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); + else + DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + mouse, count); + if (deactivateGrab) + (*mouse->DeactivateGrab)(mouse); +} + +#define AtMostOneClient \ + (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) + +void +RecalculateDeliverableEvents(pWin) + register WindowPtr pWin; +{ + register OtherClients *others; + register WindowPtr pChild; + + pChild = pWin; + while (1) + { + if (pChild->optional) + { + pChild->optional->otherEventMasks = 0; + for (others = wOtherClients(pChild); others; others = others->next) + { + pChild->optional->otherEventMasks |= others->mask; + } + } + pChild->deliverableEvents = pChild->eventMask| + wOtherEventMasks(pChild); + if (pChild->parent) + pChild->deliverableEvents |= + (pChild->parent->deliverableEvents & + ~wDontPropagateMask(pChild) & PropagateMask); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +/** + * + * \param value must conform to DeleteType + */ +int +OtherClientGone(pointer value, XID id) +{ + register OtherClientsPtr other, prev; + register WindowPtr pWin = (WindowPtr)value; + + prev = 0; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (other->resource == id) + { + if (prev) + prev->next = other->next; + else + { + if (!(pWin->optional->otherClients = other->next)) + CheckWindowOptionalNeed (pWin); + } + xfree(other); + RecalculateDeliverableEvents(pWin); + return(Success); + } + prev = other; + } + FatalError("client not on event list"); + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} + +int +EventSelectForWindow(register WindowPtr pWin, register ClientPtr client, Mask mask) +{ + Mask check; + OtherClients * others; + + if (mask & ~AllEventMasks) + { + client->errorValue = mask; + return BadValue; + } + check = (mask & AtMostOneClient); + if (check & (pWin->eventMask|wOtherEventMasks(pWin))) + { /* It is illegal for two different + clients to select on any of the + events for AtMostOneClient. However, + it is OK, for some client to + continue selecting on one of those + events. */ + if ((wClient(pWin) != client) && (check & pWin->eventMask)) + return BadAccess; + for (others = wOtherClients (pWin); others; others = others->next) + { + if (!SameClient(others, client) && (check & others->mask)) + return BadAccess; + } + } + if (wClient (pWin) == client) + { + check = pWin->eventMask; +#ifdef SGIMISC + pWin->eventMask = + (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask); +#else + pWin->eventMask = mask; +#endif + } + else + { + for (others = wOtherClients (pWin); others; others = others->next) + { + if (SameClient(others, client)) + { + check = others->mask; +#ifdef SGIMISC + mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask); +#endif + if (mask == 0) + { + FreeResource(others->resource, RT_NONE); + return Success; + } + else + others->mask = mask; + goto maskSet; + } + } + check = 0; + if (!pWin->optional && !MakeWindowOptional (pWin)) + return BadAlloc; + others = (OtherClients *) xalloc(sizeof(OtherClients)); + if (!others) + return BadAlloc; + others->mask = mask; + others->resource = FakeClientID(client->index); + others->next = pWin->optional->otherClients; + pWin->optional->otherClients = others; + if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) + return BadAlloc; + } +maskSet: + if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && + (mask & PointerMotionHintMask) && + !(check & PointerMotionHintMask) && + !inputInfo.pointer->grab) + inputInfo.pointer->valuator->motionHintWindow = NullWindow; + RecalculateDeliverableEvents(pWin); + return Success; +} + +int +EventSuppressForWindow(register WindowPtr pWin, register ClientPtr client, + Mask mask, Bool *checkOptional) +{ + register int i, free; + + if ((mask & ~PropagateMask) && !permitOldBugs) + { + client->errorValue = mask; + return BadValue; + } + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + if (!mask) + i = 0; + else + { + for (i = DNPMCOUNT, free = 0; --i > 0; ) + { + if (!DontPropagateRefCnts[i]) + free = i; + else if (mask == DontPropagateMasks[i]) + break; + } + if (!i && free) + { + i = free; + DontPropagateMasks[i] = mask; + } + } + if (i || !mask) + { + pWin->dontPropagate = i; + if (i) + DontPropagateRefCnts[i]++; + if (pWin->optional) + { + pWin->optional->dontPropagateMask = mask; + *checkOptional = TRUE; + } + } + else + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]++; + return BadAlloc; + } + pWin->dontPropagate = 0; + pWin->optional->dontPropagateMask = mask; + } + RecalculateDeliverableEvents(pWin); + return Success; +} + +static WindowPtr +CommonAncestor( + register WindowPtr a, + register WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + +static void +EnterLeaveEvent( + int type, + int mode, + int detail, + register WindowPtr pWin, + Window child) +{ + xEvent event; + register DeviceIntPtr keybd = inputInfo.keyboard; + WindowPtr focus; + register DeviceIntPtr mouse = inputInfo.pointer; + register GrabPtr grab = mouse->grab; + Mask mask; + + if ((pWin == mouse->valuator->motionHintWindow) && + (detail != NotifyInferior)) + mouse->valuator->motionHintWindow = NullWindow; + if (grab) + { + mask = (pWin == grab->window) ? grab->eventMask : 0; + if (grab->ownerEvents) + mask |= EventMaskForClient(pWin, rClient(grab)); + } + else + { + mask = pWin->eventMask | wOtherEventMasks(pWin); + } + if (mask & filters[type]) + { + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = sprite.hot.x; + event.u.enterLeave.rootY = sprite.hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(&event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; +#ifdef XKB + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else +#endif + event.u.enterLeave.state = keybd->key->state | mouse->button->state; + event.u.enterLeave.mode = mode; + focus = keybd->focus->win; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + if (grab) + (void)TryClientEvents(rClient(grab), &event, 1, mask, + filters[type], grab); + else + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], + NullGrab, 0); + } + if ((type == EnterNotify) && (mask & KeymapStateMask)) + { + xKeymapEvent ke; + +#ifdef XCSECURITY + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, keybd, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + ke.type = KeymapNotify; + if (grab) + (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, + KeymapStateMask, grab); + else + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + +static void +EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + EnterNotifies(ancestor, parent, mode, detail); + EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); +} + +static void +LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +{ + register WindowPtr pWin; + + if (ancestor == child) + return; + for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + { + EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); + child = pWin; + } +} + +static void +DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +{ + if (fromWin == toWin) + return; + if (IsParent(fromWin, toWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); + EnterNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + } + else if (IsParent(toWin, fromWin)) + { + EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); + LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + } + else + { /* neither fromWin nor toWin is descendent of the other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); + LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + } +} + +static void +FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin) +{ + xEvent event; + +#ifdef XINPUT + if (dev != inputInfo.keyboard) + { + DeviceFocusEvent(dev, type, mode, detail, pWin); + return; + } +#endif + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, + 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; +#ifdef XCSECURITY + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (!SecurityCheckDeviceAccess(client, dev, FALSE)) + { + bzero((char *)&ke.map[0], 31); + } + else +#endif + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } +} + + /* + * recursive because it is easier + * no-op if child not descended from ancestor + */ +static Bool +FocusInEvents( + DeviceIntPtr dev, + WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, + int mode, int detail, + Bool doAncestor) +{ + if (child == NullWindow) + return ancestor == NullWindow; + if (ancestor == child) + { + if (doAncestor) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, + doAncestor)) + { + if (child != skipChild) + FocusEvent(dev, FocusIn, mode, detail, child); + return TRUE; + } + return FALSE; +} + +/* dies horribly if ancestor is not an ancestor of child */ +static void +FocusOutEvents( + DeviceIntPtr dev, + WindowPtr child, WindowPtr ancestor, + int mode, int detail, + Bool doAncestor) +{ + register WindowPtr pWin; + + for (pWin = child; pWin != ancestor; pWin = pWin->parent) + FocusEvent(dev, FocusOut, mode, detail, pWin); + if (doAncestor) + FocusEvent(dev, FocusOut, mode, detail, ancestor); +} + +void +DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + + if (fromWin == toWin) + return; + out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + + if ((toWin == NullWindow) || (toWin == PointerRootWin)) + { + if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) + { + if (fromWin == PointerRootWin) + FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, + TRUE); + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); + else +#endif + for (i=0; iparent, NullWindow, mode, + NotifyNonlinearVirtual, FALSE); + } + /* Notify all the roots */ +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); + else +#endif + for (i=0; iparent != NullWindow) + (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + NotifyNonlinearVirtual, TRUE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + NotifyPointer, FALSE); + } + else + { + if (IsParent(toWin, fromWin)) + { + FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); + FocusOutEvents(dev, fromWin->parent, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); + if ((IsParent(toWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(fromWin, sprite.win)) && + (!IsParent(sprite.win, fromWin))) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + else + if (IsParent(fromWin, toWin)) + { + if ((IsParent(fromWin, sprite.win)) && + (sprite.win != fromWin) && + (!IsParent(toWin, sprite.win)) && + (!IsParent(sprite.win, toWin))) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); + (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, + NotifyVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); + } + else + { + /* neither fromWin or toWin is child of other */ + WindowPtr common = CommonAncestor(toWin, fromWin); + /* common == NullWindow ==> different screens */ + if (IsParent(fromWin, sprite.win)) + FocusOutEvents(dev, sprite.win, fromWin, mode, + NotifyPointer, FALSE); + FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); + if (fromWin->parent != NullWindow) + FocusOutEvents(dev, fromWin->parent, common, mode, + NotifyNonlinearVirtual, FALSE); + if (toWin->parent != NullWindow) + (void)FocusInEvents(dev, common, toWin, toWin, mode, + NotifyNonlinearVirtual, FALSE); + FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); + if (IsParent(toWin, sprite.win)) + (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + mode, NotifyPointer, FALSE); + } + } + } +} + +int +SetInputFocus( + ClientPtr client, + DeviceIntPtr dev, + Window focusID, + CARD8 revertTo, + Time ctime, + Bool followOK) +{ + register FocusClassPtr focus; + register WindowPtr focusWin; + int mode; + TimeStamp time; + + UpdateCurrentTime(); + if ((revertTo != RevertToParent) && + (revertTo != RevertToPointerRoot) && + (revertTo != RevertToNone) && + ((revertTo != RevertToFollowKeyboard) || !followOK)) + { + client->errorValue = revertTo; + return BadValue; + } + time = ClientTimeToServerTime(ctime); + if ((focusID == None) || (focusID == PointerRoot)) + focusWin = (WindowPtr)(long)focusID; + else if ((focusID == FollowKeyboard) && followOK) + focusWin = inputInfo.keyboard->focus->win; + else if (!(focusWin = SecurityLookupWindow(focusID, client, + SecurityReadAccess))) + return BadWindow; + else + { + /* It is a match error to try to set the input focus to an + unviewable window. */ + + if(!focusWin->realized) + return(BadMatch); + } + focus = dev->focus; + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, focus->time) == EARLIER)) + return Success; + mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + if (focus->win == FollowKeyboardWin) + DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + else + DoFocusEvents(dev, focus->win, focusWin, mode); + focus->time = time; + focus->revert = revertTo; + if (focusID == FollowKeyboard) + focus->win = FollowKeyboardWin; + else + focus->win = focusWin; + if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) + focus->traceGood = 0; + else + { + int depth = 0; + register WindowPtr pWin; + + for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; + if (depth > focus->traceSize) + { + focus->traceSize = depth+1; + Must_have_memory = TRUE; /* XXX */ + focus->trace = (WindowPtr *)xrealloc(focus->trace, + focus->traceSize * + sizeof(WindowPtr)); + Must_have_memory = FALSE; /* XXX */ + } + focus->traceGood = depth; + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + focus->trace[depth] = pWin; + } + return Success; +} + +int +ProcSetInputFocus(client) + ClientPtr client; +{ + REQUEST(xSetInputFocusReq); + + REQUEST_SIZE_MATCH(xSetInputFocusReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + return Success; +#endif + return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + stuff->revertTo, stuff->time, FALSE); +} + +int +ProcGetInputFocus(ClientPtr client) +{ + xGetInputFocusReply rep; + /* REQUEST(xReq); */ + FocusClassPtr focus = inputInfo.keyboard->focus; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (focus->win == NoneWin) + rep.focus = None; + else if (focus->win == PointerRootWin) + rep.focus = PointerRoot; + else rep.focus = focus->win->drawable.id; + rep.revertTo = focus->revert; + WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); + return Success; +} + +int +ProcGrabPointer(ClientPtr client) +{ + xGrabPointerReply rep; + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + WindowPtr pWin, confineTo; + CursorPtr cursor, oldCursor; + REQUEST(xGrabPointerReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xGrabPointerReq); + UpdateCurrentTime(); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else + { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + /* at this point, some sort of reply is guaranteed. */ + time = ClientTimeToServerTime(stuff->time); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + grab = device->grab; + if ((grab) && !SameClient(grab, client)) + rep.status = AlreadyGrabbed; + else if ((!pWin->realized) || + (confineTo && + !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + rep.status = GrabNotViewable; + else if (device->sync.frozen && + device->sync.other && !SameClient(device->sync.other, client)) + rep.status = GrabFrozen; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + rep.status = GrabInvalidTime; + else + { + GrabRec tempGrab; + + oldCursor = NullCursor; + if (grab) + { + if (grab->confineTo && !confineTo) + ConfineCursorToWindow(ROOT, FALSE, FALSE); + oldCursor = grab->cursor; + } + tempGrab.cursor = cursor; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = stuff->ownerEvents; + tempGrab.eventMask = stuff->eventMask; + tempGrab.confineTo = confineTo; + tempGrab.window = pWin; + tempGrab.keyboardMode = stuff->keyboardMode; + tempGrab.pointerMode = stuff->pointerMode; + tempGrab.device = device; + (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + if (oldCursor) + FreeCursor (oldCursor, (Cursor)0); + rep.status = GrabSuccess; + } + WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); + return Success; +} + +int +ProcChangeActivePointerGrab(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + register GrabPtr grab = device->grab; + CursorPtr newCursor, oldCursor; + REQUEST(xChangeActivePointerGrabReq); + TimeStamp time; + + REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); + if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + if (stuff->cursor == None) + newCursor = NullCursor; + else + { + newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!newCursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + if (!grab) + return Success; + if (!SameClient(grab, client)) + return Success; + time = ClientTimeToServerTime(stuff->time); + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, device->grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; + grab->cursor = newCursor; + if (newCursor) + newCursor->refcnt++; + PostNewCursor(); + if (oldCursor) + FreeCursor(oldCursor, (Cursor)0); + grab->eventMask = stuff->eventMask; + return Success; +} + +int +ProcUngrabPointer(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.pointer; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +GrabDevice(register ClientPtr client, register DeviceIntPtr dev, + unsigned this_mode, unsigned other_mode, Window grabWindow, + unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status) +{ + register WindowPtr pWin; + register GrabPtr grab; + TimeStamp time; + + UpdateCurrentTime(); + if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) + { + client->errorValue = this_mode; + return BadValue; + } + if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) + { + client->errorValue = other_mode; + return BadValue; + } + if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) + { + client->errorValue = ownerEvents; + return BadValue; + } + pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + time = ClientTimeToServerTime(ctime); + grab = dev->grab; + if (grab && !SameClient(grab, client)) + *status = AlreadyGrabbed; + else if (!pWin->realized) + *status = GrabNotViewable; + else if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + *status = GrabInvalidTime; + else if (dev->sync.frozen && + dev->sync.other && !SameClient(dev->sync.other, client)) + *status = GrabFrozen; + else + { + GrabRec tempGrab; + + tempGrab.window = pWin; + tempGrab.resource = client->clientAsMask; + tempGrab.ownerEvents = ownerEvents; + tempGrab.keyboardMode = this_mode; + tempGrab.pointerMode = other_mode; + tempGrab.eventMask = mask; + tempGrab.device = dev; + (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + *status = GrabSuccess; + } + return Success; +} + +int +ProcGrabKeyboard(ClientPtr client) +{ + xGrabKeyboardReply rep; + REQUEST(xGrabKeyboardReq); + int result; + + REQUEST_SIZE_MATCH(xGrabKeyboardReq); +#ifdef XCSECURITY + if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE)) + { + result = Success; + rep.status = AlreadyGrabbed; + } + else +#endif + result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status); + if (result != Success) + return result; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); + return Success; +} + +int +ProcUngrabKeyboard(ClientPtr client) +{ + DeviceIntPtr device = inputInfo.keyboard; + GrabPtr grab; + TimeStamp time; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + UpdateCurrentTime(); + grab = device->grab; + time = ClientTimeToServerTime(stuff->id); + if ((CompareTimeStamps(time, currentTime) != LATER) && + (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (grab) && SameClient(grab, client)) + (*device->DeactivateGrab)(device); + return Success; +} + +int +ProcQueryPointer(ClientPtr client) +{ + xQueryPointerReply rep; + WindowPtr pWin, t; + REQUEST(xResourceReq); + DeviceIntPtr mouse = inputInfo.pointer; + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.mask = mouse->button->state | inputInfo.keyboard->key->state; + rep.length = 0; + rep.root = (ROOT)->drawable.id; + rep.rootX = sprite.hot.x; + rep.rootY = sprite.hot.y; + rep.child = None; + if (sprite.hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = sprite.hot.x - pWin->drawable.x; + rep.winY = sprite.hot.y - pWin->drawable.y; + for (t = sprite.win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } + else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if(stuff->id == rep.root) { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); + + return(Success); +} + +void +InitEvents() +{ + int i; + + sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; + inputInfo.numDevices = 0; + inputInfo.devices = (DeviceIntPtr)NULL; + inputInfo.off_devices = (DeviceIntPtr)NULL; + inputInfo.keyboard = (DeviceIntPtr)NULL; + inputInfo.pointer = (DeviceIntPtr)NULL; + if (spriteTraceSize == 0) + { + spriteTraceSize = 32; + spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); + if (!spriteTrace) + FatalError("failed to allocate spriteTrace"); + } + spriteTraceGood = 0; + lastEventMask = OwnerGrabButtonMask; + filters[MotionNotify] = PointerMotionMask; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = NullWindow; + sprite.current = NullCursor; + sprite.hotLimits.x1 = 0; + sprite.hotLimits.y1 = 0; + sprite.hotLimits.x2 = 0; + sprite.hotLimits.y2 = 0; + sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; + syncEvents.replayWin = NullWindow; + while (syncEvents.pending) + { + QdEventPtr next = syncEvents.pending->next; + xfree(syncEvents.pending); + syncEvents.pending = next; + } + syncEvents.pendtail = &syncEvents.pending; + syncEvents.playingEvents = FALSE; + syncEvents.time.months = 0; + syncEvents.time.milliseconds = 0; /* hardly matters */ + currentTime.months = 0; + currentTime.milliseconds = GetTimeInMillis(); + lastDeviceEventTime = currentTime; + for (i = 0; i < DNPMCOUNT; i++) + { + DontPropagateMasks[i] = 0; + DontPropagateRefCnts[i] = 0; + } +} + +void +CloseDownEvents(void) +{ + xfree(spriteTrace); + spriteTrace = NULL; + spriteTraceSize = 0; +} + +int +ProcSendEvent(ClientPtr client) +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + REQUEST(xSendEventReq); + + REQUEST_SIZE_MATCH(xSendEventReq); + + /* The client's event type must be a core event type or one defined by an + extension. */ + + if ( ! ((stuff->event.u.u.type > X_Reply && + stuff->event.u.u.type < LASTEvent) || + (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && + stuff->event.u.u.type < (unsigned)lastEvent))) + { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + if (stuff->event.u.u.type == ClientMessage && + stuff->event.u.u.detail != 8 && + stuff->event.u.u.detail != 16 && + stuff->event.u.u.detail != 32 && + !permitOldBugs) + { + client->errorValue = stuff->event.u.u.detail; + return BadValue; + } + if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + + if (stuff->destination == PointerWindow) + pWin = sprite.win; + else if (stuff->destination == InputFocus) + { + WindowPtr inputFocus = inputInfo.keyboard->focus->win; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = ROOT; + + if (IsParent(inputFocus, sprite.win)) + { + effectiveFocus = inputFocus; + pWin = sprite.win; + } + else + effectiveFocus = pWin = inputFocus; + } + else + pWin = SecurityLookupWindow(stuff->destination, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) + { + client->errorValue = stuff->propagate; + return BadValue; + } + stuff->event.u.u.type |= 0x80; + if (stuff->propagate) + { + for (;pWin; pWin = pWin->parent) + { + if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0)) + return Success; + if (pWin == effectiveFocus) + return Success; + stuff->eventMask &= ~wDontPropagateMask(pWin); + if (!stuff->eventMask) + break; + } + } + else + (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, + NullGrab, 0); + return Success; +} + +int +ProcUngrabKey(ClientPtr client) +{ + REQUEST(xUngrabKeyReq); + WindowPtr pWin; + GrabRec tempGrab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xUngrabKeyReq); + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + tempGrab.resource = client->clientAsMask; + tempGrab.device = keybd; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = KeyPress; + tempGrab.detail.exact = stuff->key; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +int +ProcGrabKey(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xGrabKeyReq); + GrabPtr grab; + DeviceIntPtr keybd = inputInfo.keyboard; + + REQUEST_SIZE_MATCH(xGrabKeyReq); + if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) + { + client->errorValue = stuff->ownerEvents; + return(BadValue); + } + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || + (stuff->key < keybd->key->curKeySyms.minKeyCode)) + && (stuff->key != AnyKey)) + { + client->errorValue = stuff->key; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + + grab = CreateGrab(client->index, keybd, pWin, + (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, + (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, + keybd, stuff->modifiers, KeyPress, stuff->key, + NullWindow, NullCursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + + +int +ProcGrabButton(ClientPtr client) +{ + WindowPtr pWin, confineTo; + REQUEST(xGrabButtonReq); + CursorPtr cursor; + GrabPtr grab; + + REQUEST_SIZE_MATCH(xGrabButtonReq); + if ((stuff->pointerMode != GrabModeSync) && + (stuff->pointerMode != GrabModeAsync)) + { + client->errorValue = stuff->pointerMode; + return BadValue; + } + if ((stuff->keyboardMode != GrabModeSync) && + (stuff->keyboardMode != GrabModeAsync)) + { + client->errorValue = stuff->keyboardMode; + return BadValue; + } + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) + { + client->errorValue = stuff->ownerEvents; + return BadValue; + } + if (stuff->eventMask & ~PointerGrabMask) + { + client->errorValue = stuff->eventMask; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + if (stuff->confineTo == None) + confineTo = NullWindow; + else { + confineTo = SecurityLookupWindow(stuff->confineTo, client, + SecurityReadAccess); + if (!confineTo) + return BadWindow; + } + if (stuff->cursor == None) + cursor = NullCursor; + else + { + cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursor) + { + client->errorValue = stuff->cursor; + return BadCursor; + } + } + + + grab = CreateGrab(client->index, inputInfo.pointer, pWin, + permitOldBugs ? (Mask)(stuff->eventMask | + ButtonPressMask | ButtonReleaseMask) : + (Mask)stuff->eventMask, + (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, + (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers, + ButtonPress, stuff->button, confineTo, cursor); + if (!grab) + return BadAlloc; + return AddPassiveGrabToList(grab); +} + +int +ProcUngrabButton(ClientPtr client) +{ + REQUEST(xUngrabButtonReq); + WindowPtr pWin; + GrabRec tempGrab; + + REQUEST_SIZE_MATCH(xUngrabButtonReq); + if ((stuff->modifiers != AnyModifier) && + (stuff->modifiers & ~AllModifiersMask)) + { + client->errorValue = stuff->modifiers; + return BadValue; + } + pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess); + if (!pWin) + return BadWindow; + tempGrab.resource = client->clientAsMask; + tempGrab.device = inputInfo.pointer; + tempGrab.window = pWin; + tempGrab.modifiersDetail.exact = stuff->modifiers; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.modifierDevice = inputInfo.keyboard; + tempGrab.type = ButtonPress; + tempGrab.detail.exact = stuff->button; + tempGrab.detail.pMask = NULL; + + if (!DeletePassiveGrabFromList(&tempGrab)) + return(BadAlloc); + return(Success); +} + +void +DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) +{ + WindowPtr parent; + DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr keybd = inputInfo.keyboard; + FocusClassPtr focus = keybd->focus; + OtherClientsPtr oc; + GrabPtr passive; + + + /* Deactivate any grabs performed on this window, before making any + input focus changes. */ + + if (mouse->grab && + ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) + (*mouse->DeactivateGrab)(mouse); + + /* Deactivating a keyboard grab should cause focus events. */ + + if (keybd->grab && (keybd->grab->window == pWin)) + (*keybd->DeactivateGrab)(keybd); + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized +/* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ +#ifdef NOTDEF + || clients[CLIENT_ID(parent->drawable.id)]->clientGone +#endif + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + + if (mouse->valuator->motionHintWindow == pWin) + mouse->valuator->motionHintWindow = NullWindow; + + if (freeResources) + { + if (pWin->dontPropagate) + DontPropagateRefCnts[pWin->dontPropagate]--; + while ( (oc = wOtherClients(pWin)) ) + FreeResource(oc->resource, RT_NONE); + while ( (passive = wPassiveGrabs(pWin)) ) + FreeResource(passive->resource, RT_NONE); + } +#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); +#endif +} + +/** + * Call this whenever some window at or below pWin has changed geometry + */ +void +CheckCursorConfinement(WindowPtr pWin) +{ + GrabPtr grab = inputInfo.pointer->grab; + WindowPtr confineTo; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; +#endif + + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(confineTo)) + (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(confineTo, TRUE, TRUE); + } +} + +Mask +EventMaskForClient(WindowPtr pWin, ClientPtr client) +{ + register OtherClientsPtr other; + + if (wClient (pWin) == client) + return pWin->eventMask; + for (other = wOtherClients(pWin); other; other = other->next) + { + if (SameClient(other, client)) + return other->mask; + } + return 0; +} + +int +ProcRecolorCursor(ClientPtr client) +{ + CursorPtr pCursor; + int nscr; + ScreenPtr pscr; + Bool displayed; + REQUEST(xRecolorCursorReq); + + REQUEST_SIZE_MATCH(xRecolorCursorReq); + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, SecurityWriteAccess); + if ( !pCursor) + { + client->errorValue = stuff->cursor; + return (BadCursor); + } + + pCursor->foreRed = stuff->foreRed; + pCursor->foreGreen = stuff->foreGreen; + pCursor->foreBlue = stuff->foreBlue; + + pCursor->backRed = stuff->backRed; + pCursor->backGreen = stuff->backGreen; + pCursor->backBlue = stuff->backBlue; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; +#ifdef PANORAMIX + if(!noPanoramiXExtension) + displayed = (pscr == sprite.screen); + else +#endif + displayed = (pscr == sprite.hotPhys.pScreen); + ( *pscr->RecolorCursor)(pscr, pCursor, + (pCursor == sprite.current) && displayed); + } + return (Success); +} + +void +WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) +{ +#ifdef PANORAMIX + xEvent eventCopy; +#endif + xEvent eventTo, *eventFrom; + int i; + +#ifdef XKB + if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) + return; +#endif + +#ifdef PANORAMIX + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + { + switch(events->u.u.type) { + case MotionNotify: + case ButtonPress: + case ButtonRelease: + case KeyPress: + case KeyRelease: + case EnterNotify: + case LeaveNotify: + /* + When multiple clients want the same event DeliverEventsToWindow + passes the same event structure multiple times so we can't + modify the one passed to us + */ + count = 1; /* should always be 1 */ + memcpy(&eventCopy, events, sizeof(xEvent)); + eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) + { + eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; + eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; + } + events = &eventCopy; + break; + default: break; + } + } +#endif + + if (EventCallback) + { + EventInfoRec eventinfo; + eventinfo.client = pClient; + eventinfo.events = events; + eventinfo.count = count; + CallCallbacks(&EventCallback, (pointer)&eventinfo); + } + if(pClient->swapped) + { + for(i = 0; i < count; i++) + { + eventFrom = &events[i]; + /* Remember to strip off the leading bit of type in case + this event was sent with "SendEvent." */ + (*EventSwapVector[eventFrom->u.u.type & 0177]) + (eventFrom, &eventTo); + (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + } + } + else + { + (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c new file mode 100644 index 000000000..a510c9356 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c @@ -0,0 +1,508 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.11 2001/12/14 19:59:31 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "../../dix/dispatch.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#include "Trap.h" + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +ExtensionEntry * +AddExtension(char *name, int NumEvents, int NumErrors, + int (*MainProc)(ClientPtr c1), + int (*SwappedMainProc)(ClientPtr c2), + void (*CloseDownProc)(ExtensionEntry *e), + unsigned short (*MinorOpcodeProc)(ClientPtr c3)) +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry)); + if (!ext) + return((ExtensionEntry *) NULL); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + +#ifdef LBX + (void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase); +#endif + return(ext); +} + +Bool AddExtensionAlias(char *alias, ExtensionEntry *ext) +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; +#ifdef LBX + return LbxAddExtensionAlias(ext->index, alias); +#else + return TRUE; +#endif +} + +static int +FindExtension(char *extname, int len) +{ + int i, j; + + for (i=0; iname) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +/* + * CheckExtension returns the extensions[] entry for the requested + * extension name. Maybe this could just return a Bool instead? + */ +ExtensionEntry * +CheckExtension(const char *extname) +{ + int n; + + n = FindExtension((char*)extname, strlen(extname)); + if (n != -1) + return extensions[n]; + else + return NULL; +} + +void +DeclareExtensionSecurity(char *extname, Bool secure) +{ +#ifdef XCSECURITY + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + { + int majorop = extensions[i]->base; + extensions[i]->secure = secure; + if (secure) + { + UntrustedProcVector[majorop] = ProcVector[majorop]; + SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop]; + } + else + { + UntrustedProcVector[majorop] = ProcBadRequest; + SwappedUntrustedProcVector[majorop] = ProcBadRequest; + } + } +#endif +#ifdef LBX + LbxDeclareExtensionSecurity(extname, secure); +#endif +} + +unsigned short +StandardMinorOpcode(ClientPtr client) +{ + return ((xReq *)client->requestBuffer)->data; +} + +unsigned short +MinorOpcodeOfRequest(ClientPtr client) +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + +#ifdef LBX + LbxCloseDownExtensions(); +#endif + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; inum) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(ClientPtr client) +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 + + /* + * Hide RENDER if our implementation + * is faulty. + */ + + || (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(ClientPtr client) +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + /* + * Hide RENDER if our implementation + * is faulty. + */ + + if (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) + continue; + + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(char *name, GCPtr pGC) +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(char *name, GC *pGC, ExtensionLookupProc proc) +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(char *name, ScreenPtr pScreen, ExtensionLookupProc proc) +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.NX.original new file mode 100644 index 000000000..a510c9356 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.NX.original @@ -0,0 +1,508 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.11 2001/12/14 19:59:31 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "../../dix/dispatch.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#include "Trap.h" + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +ExtensionEntry * +AddExtension(char *name, int NumEvents, int NumErrors, + int (*MainProc)(ClientPtr c1), + int (*SwappedMainProc)(ClientPtr c2), + void (*CloseDownProc)(ExtensionEntry *e), + unsigned short (*MinorOpcodeProc)(ClientPtr c3)) +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry)); + if (!ext) + return((ExtensionEntry *) NULL); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + +#ifdef LBX + (void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase); +#endif + return(ext); +} + +Bool AddExtensionAlias(char *alias, ExtensionEntry *ext) +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; +#ifdef LBX + return LbxAddExtensionAlias(ext->index, alias); +#else + return TRUE; +#endif +} + +static int +FindExtension(char *extname, int len) +{ + int i, j; + + for (i=0; iname) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +/* + * CheckExtension returns the extensions[] entry for the requested + * extension name. Maybe this could just return a Bool instead? + */ +ExtensionEntry * +CheckExtension(const char *extname) +{ + int n; + + n = FindExtension((char*)extname, strlen(extname)); + if (n != -1) + return extensions[n]; + else + return NULL; +} + +void +DeclareExtensionSecurity(char *extname, Bool secure) +{ +#ifdef XCSECURITY + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + { + int majorop = extensions[i]->base; + extensions[i]->secure = secure; + if (secure) + { + UntrustedProcVector[majorop] = ProcVector[majorop]; + SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop]; + } + else + { + UntrustedProcVector[majorop] = ProcBadRequest; + SwappedUntrustedProcVector[majorop] = ProcBadRequest; + } + } +#endif +#ifdef LBX + LbxDeclareExtensionSecurity(extname, secure); +#endif +} + +unsigned short +StandardMinorOpcode(ClientPtr client) +{ + return ((xReq *)client->requestBuffer)->data; +} + +unsigned short +MinorOpcodeOfRequest(ClientPtr client) +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + +#ifdef LBX + LbxCloseDownExtensions(); +#endif + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; inum) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(ClientPtr client) +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 + + /* + * Hide RENDER if our implementation + * is faulty. + */ + + || (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(ClientPtr client) +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + /* + * Hide RENDER if our implementation + * is faulty. + */ + + if (nxagentRenderTrap && strcmp(extensions[i]->name, "RENDER") == 0) + continue; + + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(char *name, GCPtr pGC) +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(char *name, GC *pGC, ExtensionLookupProc proc) +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(char *name, ScreenPtr pScreen, ExtensionLookupProc proc) +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.X.original new file mode 100644 index 000000000..270d54f9b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.X.original @@ -0,0 +1,474 @@ +/* $XFree86: xc/programs/Xserver/dix/extension.c,v 3.11 2001/12/14 19:59:31 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: extension.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_EVENTS +#define NEED_REPLIES +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "dispatch.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef LBX +#include "lbxserve.h" +#endif + +#define EXTENSION_BASE 128 +#define EXTENSION_EVENT_BASE 64 +#define LAST_EVENT 128 +#define LAST_ERROR 255 + +ScreenProcEntry AuxillaryScreenProcs[MAXSCREENS]; + +static ExtensionEntry **extensions = (ExtensionEntry **)NULL; + +int lastEvent = EXTENSION_EVENT_BASE; +static int lastError = FirstExtensionError; +static unsigned int NumExtensions = 0; + +ExtensionEntry * +AddExtension(char *name, int NumEvents, int NumErrors, + int (*MainProc)(ClientPtr c1), + int (*SwappedMainProc)(ClientPtr c2), + void (*CloseDownProc)(ExtensionEntry *e), + unsigned short (*MinorOpcodeProc)(ClientPtr c3)) +{ + int i; + register ExtensionEntry *ext, **newexts; + + if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + return((ExtensionEntry *) NULL); + if ((lastEvent + NumEvents > LAST_EVENT) || + (unsigned)(lastError + NumErrors > LAST_ERROR)) + return((ExtensionEntry *) NULL); + + ext = (ExtensionEntry *) xalloc(sizeof(ExtensionEntry)); + if (!ext) + return((ExtensionEntry *) NULL); + ext->name = (char *)xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **)NULL; + if (!ext->name) + { + xfree(ext); + return((ExtensionEntry *) NULL); + } + strcpy(ext->name, name); + i = NumExtensions; + newexts = (ExtensionEntry **) xrealloc(extensions, + (i + 1) * sizeof(ExtensionEntry *)); + if (!newexts) + { + xfree(ext->name); + xfree(ext); + return((ExtensionEntry *) NULL); + } + NumExtensions++; + extensions = newexts; + extensions[i] = ext; + ext->index = i; + ext->base = i + EXTENSION_BASE; + ext->CloseDown = CloseDownProc; + ext->MinorOpcode = MinorOpcodeProc; + ProcVector[i + EXTENSION_BASE] = MainProc; + SwappedProcVector[i + EXTENSION_BASE] = SwappedMainProc; + if (NumEvents) + { + ext->eventBase = lastEvent; + ext->eventLast = lastEvent + NumEvents; + lastEvent += NumEvents; + } + else + { + ext->eventBase = 0; + ext->eventLast = 0; + } + if (NumErrors) + { + ext->errorBase = lastError; + ext->errorLast = lastError + NumErrors; + lastError += NumErrors; + } + else + { + ext->errorBase = 0; + ext->errorLast = 0; + } +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + +#ifdef LBX + (void) LbxAddExtension(name, ext->base, ext->eventBase, ext->errorBase); +#endif + return(ext); +} + +Bool AddExtensionAlias(char *alias, ExtensionEntry *ext) +{ + char *name; + char **aliases; + + aliases = (char **)xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *)xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; +#ifdef LBX + return LbxAddExtensionAlias(ext->index, alias); +#else + return TRUE; +#endif +} + +static int +FindExtension(char *extname, int len) +{ + int i, j; + + for (i=0; iname) == len) && + !strncmp(extname, extensions[i]->name, len)) + break; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + if ((strlen(extensions[i]->aliases[j]) == len) && + !strncmp(extname, extensions[i]->aliases[j], len)) + break; + } + if (j >= 0) break; + } + return ((i == NumExtensions) ? -1 : i); +} + +/* + * CheckExtension returns the extensions[] entry for the requested + * extension name. Maybe this could just return a Bool instead? + */ +ExtensionEntry * +CheckExtension(const char *extname) +{ + int n; + + n = FindExtension((char*)extname, strlen(extname)); + if (n != -1) + return extensions[n]; + else + return NULL; +} + +void +DeclareExtensionSecurity(char *extname, Bool secure) +{ +#ifdef XCSECURITY + int i = FindExtension(extname, strlen(extname)); + if (i >= 0) + { + int majorop = extensions[i]->base; + extensions[i]->secure = secure; + if (secure) + { + UntrustedProcVector[majorop] = ProcVector[majorop]; + SwappedUntrustedProcVector[majorop] = SwappedProcVector[majorop]; + } + else + { + UntrustedProcVector[majorop] = ProcBadRequest; + SwappedUntrustedProcVector[majorop] = ProcBadRequest; + } + } +#endif +#ifdef LBX + LbxDeclareExtensionSecurity(extname, secure); +#endif +} + +unsigned short +StandardMinorOpcode(ClientPtr client) +{ + return ((xReq *)client->requestBuffer)->data; +} + +unsigned short +MinorOpcodeOfRequest(ClientPtr client) +{ + unsigned char major; + + major = ((xReq *)client->requestBuffer)->reqType; + if (major < EXTENSION_BASE) + return 0; + major -= EXTENSION_BASE; + if (major >= NumExtensions) + return 0; + return (*extensions[major]->MinorOpcode)(client); +} + +void +CloseDownExtensions() +{ + register int i,j; + +#ifdef LBX + LbxCloseDownExtensions(); +#endif + + for (i = NumExtensions - 1; i >= 0; i--) + { + (* extensions[i]->CloseDown)(extensions[i]); + NumExtensions = i; + xfree(extensions[i]->name); + for (j = extensions[i]->num_aliases; --j >= 0;) + xfree(extensions[i]->aliases[j]); + xfree(extensions[i]->aliases); + xfree(extensions[i]); + } + xfree(extensions); + extensions = (ExtensionEntry **)NULL; + lastEvent = EXTENSION_EVENT_BASE; + lastError = FirstExtensionError; + for (i=0; inum) + { + spentry->num--; + xfree(spentry->procList[spentry->num].name); + } + xfree(spentry->procList); + spentry->procList = (ProcEntryPtr)NULL; + } +} + + +int +ProcQueryExtension(ClientPtr client) +{ + xQueryExtensionReply reply; + int i; + REQUEST(xQueryExtensionReq); + + REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes); + + reply.type = X_Reply; + reply.length = 0; + reply.major_opcode = 0; + reply.sequenceNumber = client->sequence; + + if ( ! NumExtensions ) + reply.present = xFalse; + else + { + i = FindExtension((char *)&stuff[1], stuff->nbytes); + if (i < 0 +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) +#endif + ) + reply.present = xFalse; + else + { + reply.present = xTrue; + reply.major_opcode = extensions[i]->base; + reply.first_event = extensions[i]->eventBase; + reply.first_error = extensions[i]->errorBase; + } + } + WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply); + return(client->noClientException); +} + +int +ProcListExtensions(ClientPtr client) +{ + xListExtensionsReply reply; + char *bufptr, *buffer; + int total_length = 0; + + REQUEST_SIZE_MATCH(xReq); + + reply.type = X_Reply; + reply.nExtensions = 0; + reply.length = 0; + reply.sequenceNumber = client->sequence; + buffer = NULL; + + if ( NumExtensions ) + { + register int i, j; + + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + total_length += strlen(extensions[i]->name) + 1; + reply.nExtensions += 1 + extensions[i]->num_aliases; + for (j = extensions[i]->num_aliases; --j >= 0;) + total_length += strlen(extensions[i]->aliases[j]) + 1; + } + reply.length = (total_length + 3) >> 2; + buffer = bufptr = (char *)ALLOCATE_LOCAL(total_length); + if (!buffer) + return(BadAlloc); + for (i=0; itrustLevel == XSecurityClientUntrusted && + !extensions[i]->secure) + continue; +#endif + *bufptr++ = len = strlen(extensions[i]->name); + memmove(bufptr, extensions[i]->name, len); + bufptr += len; + for (j = extensions[i]->num_aliases; --j >= 0;) + { + *bufptr++ = len = strlen(extensions[i]->aliases[j]); + memmove(bufptr, extensions[i]->aliases[j], len); + bufptr += len; + } + } + } + WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply); + if (reply.length) + { + WriteToClient(client, total_length, buffer); + DEALLOCATE_LOCAL(buffer); + } + return(client->noClientException); +} + + +ExtensionLookupProc +LookupProc(char *name, GCPtr pGC) +{ + register int i; + register ScreenProcEntry *spentry; + spentry = &AuxillaryScreenProcs[pGC->pScreen->myNum]; + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + return(spentry->procList[i].proc); + } + return (ExtensionLookupProc)NULL; +} + +Bool +RegisterProc(char *name, GC *pGC, ExtensionLookupProc proc) +{ + return RegisterScreenProc(name, pGC->pScreen, proc); +} + +Bool +RegisterScreenProc(char *name, ScreenPtr pScreen, ExtensionLookupProc proc) +{ + register ScreenProcEntry *spentry; + register ProcEntryPtr procEntry = (ProcEntryPtr)NULL; + char *newname; + int i; + + spentry = &AuxillaryScreenProcs[pScreen->myNum]; + /* first replace duplicates */ + if (spentry->num) + { + for (i = 0; i < spentry->num; i++) + if (strcmp(name, spentry->procList[i].name) == 0) + { + procEntry = &spentry->procList[i]; + break; + } + } + if (procEntry) + procEntry->proc = proc; + else + { + newname = (char *)xalloc(strlen(name)+1); + if (!newname) + return FALSE; + procEntry = (ProcEntryPtr) + xrealloc(spentry->procList, + sizeof(ProcEntryRec) * (spentry->num+1)); + if (!procEntry) + { + xfree(newname); + return FALSE; + } + spentry->procList = procEntry; + procEntry += spentry->num; + procEntry->name = newname; + strcpy(newname, name); + procEntry->proc = proc; + spentry->num++; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c new file mode 100644 index 000000000..aee27e820 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c @@ -0,0 +1,575 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/GL/glx/glxext.c,v 1.9 2003/09/28 20:15:43 alanh Exp $ +** The contents of this file are subject to the GLX Public License Version 1.0 +** (the "License"). You may not use this file except in compliance with the +** License. You may obtain a copy of the License at Silicon Graphics, Inc., +** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +** or at http://www.sgi.com/software/opensource/glx/license.html. +** +** Software distributed under the License is distributed on an "AS IS" +** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY +** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR +** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific +** language governing rights and limitations under the License. +** +** The Original Software is GLX version 1.2 source code, released February, +** 1999. The developer of the Original Software is Silicon Graphics, Inc. +** Those portions of the Subject Software created by Silicon Graphics, Inc. +** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. +** +*/ + +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glxserver.h" +#include +#include +#include +#include "g_disptab.h" +#include "unpack.h" +#include "glxutil.h" +#include "glxext.h" +#include "micmap.h" + +#include "Trap.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +void GlxWrapInitVisuals(miInitVisualsProcPtr *); +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates); + +static __GLXextensionInfo *__glXExt /* = &__glDDXExtensionInfo */; + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + (*__glXExt->resetExtension)(); + __glXScreenReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + + if (cl->returnBuf) __glXFree(cl->returnBuf); + if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); + if (cl->currentContexts) __glXFree(cl->currentContexts); + __glXMemset(cl, 0, sizeof(__GLXclientState)); + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + +} + +/* +** Reset state used to keep track of large (multi-request) commands. +*/ +void __glXResetLargeCommandStatus(__GLXclientState *cl) +{ + cl->largeCmdBytesSoFar = 0; + cl->largeCmdBytesTotal = 0; + cl->largeCmdRequestsSoFar = 0; + cl->largeCmdRequestsTotal = 0; +} + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + __glXDeassociateContext(cx); + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + pGlxPixmap->idExists = False; + if (!pGlxPixmap->refcnt) { + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + __glXFree(pGlxPixmap); + } + + return True; +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + if (!cx->isDirect) { + if ((*cx->gc->exports.destroyContext)((__GLcontext *)cx->gc) == GL_FALSE) { + return GL_FALSE; + } + } + if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); + if (cx->selectBuf) __glXFree(cx->selectBuf); + __glXFree(cx); + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +extern RESTYPE __glXSwapBarrierRes; + +static int SwapBarrierGone(int screen, XID drawable) +{ + if (__glXSwapBarrierFuncs && + __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc != NULL) { + __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc(screen, drawable, 0); + } + FreeResourceByType(drawable, __glXSwapBarrierRes, FALSE); + return True; +} + +/************************************************************************/ + +/* +** These routines can be used to check whether a particular GL command +** has caused an error. Specifically, we use them to check whether a +** given query has caused an error, in which case a zero-length data +** reply is sent to the client. +*/ + +static GLboolean errorOccured = GL_FALSE; + +/* +** The GL was will call this routine if an error occurs. +*/ +void __glXErrorCallBack(__GLinterface *gc, GLenum code) +{ + errorOccured = GL_TRUE; +} + +/* +** Clear the error flag before calling the GL command. +*/ +void __glXClearErrorOccured(void) +{ + errorOccured = GL_FALSE; +} + +/* +** Check if the GL command caused an error. +*/ +GLboolean __glXErrorOccured(void) +{ + return errorOccured; +} + +/************************************************************************/ + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone); + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + + __glXSwapBarrierRes = CreateNewResourceType((DeleteType)SwapBarrierGone); + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return __glXExt->type; +} + +/************************************************************************/ + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + (*__glXExt->setVisualConfigs)(nconfigs, configs, privates); +} + +static miInitVisualsProcPtr saveInitVisualsProc; + +Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, + int *nvisualp, int *ndepthp, + int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, + int preferredVis) +{ + Bool ret; + + if (saveInitVisualsProc) { + ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, + rootDepthp, defaultVisp, sizes, bitsPerRGB, + preferredVis); + if (!ret) + return False; + } + (*__glXExt->initVisuals)(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB); + return True; +} + +void +GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) +{ + saveInitVisualsProc = *initVisProc; + *initVisProc = GlxInitVisuals; + /* HACK: this shouldn't be done here but it's the earliest time */ + __glXExt = __glXglDDXExtensionInfo(); /* from GLcore */ +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/* +** Make a context the current one for the GL (in this implementation, there +** is only one instance of the GL, and we use it to serve all GL clients by +** switching it between different contexts). While we are at it, look up +** a context by its tag and return its (__GLXcontext *). +*/ +__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, + int *error) +{ + __GLXcontext *cx; + + /* + ** See if the context tag is legal; it is managed by the extension, + ** so if it's invalid, we have an implementation error. + */ + cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag); + if (!cx) { + cl->client->errorValue = tag; + *error = __glXBadContextTag; + return 0; + } + + if (!cx->isDirect) { + if (cx->drawPriv == NULL) { + /* + ** The drawable has vanished. It must be a window, because only + ** windows can be destroyed from under us; GLX pixmaps are + ** refcounted and don't go away until no one is using them. + */ + *error = __glXBadCurrentWindow; + return 0; + } + } + + if (cx == __glXLastContext) { + /* No need to re-bind */ + return cx; + } + + /* Make this context the current one for the GL. */ + if (!cx->isDirect) { + if (!(*cx->gc->exports.forceCurrent)((__GLcontext *)cx->gc)) { + /* Bind failed, and set the error code. Bummer */ + cl->client->errorValue = cx->id; + *error = __glXBadContextState; + return 0; + } + } + __glXLastContext = cx; + return cx; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** If we're expecting a glXRenderLarge request, this better be one. + */ + if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) { + client->errorValue = stuff->glxCode; + return __glXBadLargeRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +static int __glXSwapDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.NX.original new file mode 100644 index 000000000..aee27e820 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.NX.original @@ -0,0 +1,575 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/GL/glx/glxext.c,v 1.9 2003/09/28 20:15:43 alanh Exp $ +** The contents of this file are subject to the GLX Public License Version 1.0 +** (the "License"). You may not use this file except in compliance with the +** License. You may obtain a copy of the License at Silicon Graphics, Inc., +** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +** or at http://www.sgi.com/software/opensource/glx/license.html. +** +** Software distributed under the License is distributed on an "AS IS" +** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY +** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR +** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific +** language governing rights and limitations under the License. +** +** The Original Software is GLX version 1.2 source code, released February, +** 1999. The developer of the Original Software is Silicon Graphics, Inc. +** Those portions of the Subject Software created by Silicon Graphics, Inc. +** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. +** +*/ + +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glxserver.h" +#include +#include +#include +#include "g_disptab.h" +#include "unpack.h" +#include "glxutil.h" +#include "glxext.h" +#include "micmap.h" + +#include "Trap.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +void GlxWrapInitVisuals(miInitVisualsProcPtr *); +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates); + +static __GLXextensionInfo *__glXExt /* = &__glDDXExtensionInfo */; + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + (*__glXExt->resetExtension)(); + __glXScreenReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + + if (cl->returnBuf) __glXFree(cl->returnBuf); + if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); + if (cl->currentContexts) __glXFree(cl->currentContexts); + __glXMemset(cl, 0, sizeof(__GLXclientState)); + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + +} + +/* +** Reset state used to keep track of large (multi-request) commands. +*/ +void __glXResetLargeCommandStatus(__GLXclientState *cl) +{ + cl->largeCmdBytesSoFar = 0; + cl->largeCmdBytesTotal = 0; + cl->largeCmdRequestsSoFar = 0; + cl->largeCmdRequestsTotal = 0; +} + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + __glXDeassociateContext(cx); + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + pGlxPixmap->idExists = False; + if (!pGlxPixmap->refcnt) { + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + __glXFree(pGlxPixmap); + } + + return True; +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + if (!cx->isDirect) { + if ((*cx->gc->exports.destroyContext)((__GLcontext *)cx->gc) == GL_FALSE) { + return GL_FALSE; + } + } + if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); + if (cx->selectBuf) __glXFree(cx->selectBuf); + __glXFree(cx); + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +extern RESTYPE __glXSwapBarrierRes; + +static int SwapBarrierGone(int screen, XID drawable) +{ + if (__glXSwapBarrierFuncs && + __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc != NULL) { + __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc(screen, drawable, 0); + } + FreeResourceByType(drawable, __glXSwapBarrierRes, FALSE); + return True; +} + +/************************************************************************/ + +/* +** These routines can be used to check whether a particular GL command +** has caused an error. Specifically, we use them to check whether a +** given query has caused an error, in which case a zero-length data +** reply is sent to the client. +*/ + +static GLboolean errorOccured = GL_FALSE; + +/* +** The GL was will call this routine if an error occurs. +*/ +void __glXErrorCallBack(__GLinterface *gc, GLenum code) +{ + errorOccured = GL_TRUE; +} + +/* +** Clear the error flag before calling the GL command. +*/ +void __glXClearErrorOccured(void) +{ + errorOccured = GL_FALSE; +} + +/* +** Check if the GL command caused an error. +*/ +GLboolean __glXErrorOccured(void) +{ + return errorOccured; +} + +/************************************************************************/ + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone); + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + + __glXSwapBarrierRes = CreateNewResourceType((DeleteType)SwapBarrierGone); + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return __glXExt->type; +} + +/************************************************************************/ + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + (*__glXExt->setVisualConfigs)(nconfigs, configs, privates); +} + +static miInitVisualsProcPtr saveInitVisualsProc; + +Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, + int *nvisualp, int *ndepthp, + int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, + int preferredVis) +{ + Bool ret; + + if (saveInitVisualsProc) { + ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, + rootDepthp, defaultVisp, sizes, bitsPerRGB, + preferredVis); + if (!ret) + return False; + } + (*__glXExt->initVisuals)(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB); + return True; +} + +void +GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) +{ + saveInitVisualsProc = *initVisProc; + *initVisProc = GlxInitVisuals; + /* HACK: this shouldn't be done here but it's the earliest time */ + __glXExt = __glXglDDXExtensionInfo(); /* from GLcore */ +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/* +** Make a context the current one for the GL (in this implementation, there +** is only one instance of the GL, and we use it to serve all GL clients by +** switching it between different contexts). While we are at it, look up +** a context by its tag and return its (__GLXcontext *). +*/ +__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, + int *error) +{ + __GLXcontext *cx; + + /* + ** See if the context tag is legal; it is managed by the extension, + ** so if it's invalid, we have an implementation error. + */ + cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag); + if (!cx) { + cl->client->errorValue = tag; + *error = __glXBadContextTag; + return 0; + } + + if (!cx->isDirect) { + if (cx->drawPriv == NULL) { + /* + ** The drawable has vanished. It must be a window, because only + ** windows can be destroyed from under us; GLX pixmaps are + ** refcounted and don't go away until no one is using them. + */ + *error = __glXBadCurrentWindow; + return 0; + } + } + + if (cx == __glXLastContext) { + /* No need to re-bind */ + return cx; + } + + /* Make this context the current one for the GL. */ + if (!cx->isDirect) { + if (!(*cx->gc->exports.forceCurrent)((__GLcontext *)cx->gc)) { + /* Bind failed, and set the error code. Bummer */ + cl->client->errorValue = cx->id; + *error = __glXBadContextState; + return 0; + } + } + __glXLastContext = cx; + return cx; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** If we're expecting a glXRenderLarge request, this better be one. + */ + if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) { + client->errorValue = stuff->glxCode; + return __glXBadLargeRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +static int __glXSwapDispatch(ClientPtr client) +{ + int result; + + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + + /* + * Report upstream that we are + * dispatching a GLX operation. + */ + + nxagentGlxTrap = 1; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Going to dispatch GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + result = (*proc)(cl, (GLbyte *) stuff); + + nxagentGlxTrap = 0; + + #ifdef TEST + fprintf(stderr, "__glXDispatch: Dispatched GLX operation [%d] for client [%d].\n", + opcode, client -> index); + #endif + + return result; +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.X.original new file mode 100644 index 000000000..fa1382983 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.X.original @@ -0,0 +1,505 @@ +/* $XFree86: xc/programs/Xserver/GL/glx/glxext.c,v 1.9 2003/09/28 20:15:43 alanh Exp $ +** The contents of this file are subject to the GLX Public License Version 1.0 +** (the "License"). You may not use this file except in compliance with the +** License. You may obtain a copy of the License at Silicon Graphics, Inc., +** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +** or at http://www.sgi.com/software/opensource/glx/license.html. +** +** Software distributed under the License is distributed on an "AS IS" +** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY +** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR +** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific +** language governing rights and limitations under the License. +** +** The Original Software is GLX version 1.2 source code, released February, +** 1999. The developer of the Original Software is Silicon Graphics, Inc. +** Those portions of the Subject Software created by Silicon Graphics, Inc. +** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. +** +*/ + +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "glxserver.h" +#include +#include +#include +#include "g_disptab.h" +#include "unpack.h" +#include "glxutil.h" +#include "glxext.h" +#include "micmap.h" + + +void GlxWrapInitVisuals(miInitVisualsProcPtr *); +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates); + +static __GLXextensionInfo *__glXExt /* = &__glDDXExtensionInfo */; + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + (*__glXExt->resetExtension)(); + __glXScreenReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + + if (cl->returnBuf) __glXFree(cl->returnBuf); + if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); + if (cl->currentContexts) __glXFree(cl->currentContexts); + __glXMemset(cl, 0, sizeof(__GLXclientState)); + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + +} + +/* +** Reset state used to keep track of large (multi-request) commands. +*/ +void __glXResetLargeCommandStatus(__GLXclientState *cl) +{ + cl->largeCmdBytesSoFar = 0; + cl->largeCmdBytesTotal = 0; + cl->largeCmdRequestsSoFar = 0; + cl->largeCmdRequestsTotal = 0; +} + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + __glXDeassociateContext(cx); + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + pGlxPixmap->idExists = False; + if (!pGlxPixmap->refcnt) { + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + __glXFree(pGlxPixmap); + } + + return True; +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + if (!cx->isDirect) { + if ((*cx->gc->exports.destroyContext)((__GLcontext *)cx->gc) == GL_FALSE) { + return GL_FALSE; + } + } + if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); + if (cx->selectBuf) __glXFree(cx->selectBuf); + __glXFree(cx); + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +extern RESTYPE __glXSwapBarrierRes; + +static int SwapBarrierGone(int screen, XID drawable) +{ + if (__glXSwapBarrierFuncs && + __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc != NULL) { + __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc(screen, drawable, 0); + } + FreeResourceByType(drawable, __glXSwapBarrierRes, FALSE); + return True; +} + +/************************************************************************/ + +/* +** These routines can be used to check whether a particular GL command +** has caused an error. Specifically, we use them to check whether a +** given query has caused an error, in which case a zero-length data +** reply is sent to the client. +*/ + +static GLboolean errorOccured = GL_FALSE; + +/* +** The GL was will call this routine if an error occurs. +*/ +void __glXErrorCallBack(__GLinterface *gc, GLenum code) +{ + errorOccured = GL_TRUE; +} + +/* +** Clear the error flag before calling the GL command. +*/ +void __glXClearErrorOccured(void) +{ + errorOccured = GL_FALSE; +} + +/* +** Check if the GL command caused an error. +*/ +GLboolean __glXErrorOccured(void) +{ + return errorOccured; +} + +/************************************************************************/ + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone); + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + + __glXSwapBarrierRes = CreateNewResourceType((DeleteType)SwapBarrierGone); + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return __glXExt->type; +} + +/************************************************************************/ + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + (*__glXExt->setVisualConfigs)(nconfigs, configs, privates); +} + +static miInitVisualsProcPtr saveInitVisualsProc; + +Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, + int *nvisualp, int *ndepthp, + int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, + int preferredVis) +{ + Bool ret; + + if (saveInitVisualsProc) { + ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, + rootDepthp, defaultVisp, sizes, bitsPerRGB, + preferredVis); + if (!ret) + return False; + } + (*__glXExt->initVisuals)(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB); + return True; +} + +void +GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) +{ + saveInitVisualsProc = *initVisProc; + *initVisProc = GlxInitVisuals; + /* HACK: this shouldn't be done here but it's the earliest time */ + __glXExt = __glXglDDXExtensionInfo(); /* from GLcore */ +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/* +** Make a context the current one for the GL (in this implementation, there +** is only one instance of the GL, and we use it to serve all GL clients by +** switching it between different contexts). While we are at it, look up +** a context by its tag and return its (__GLXcontext *). +*/ +__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, + int *error) +{ + __GLXcontext *cx; + + /* + ** See if the context tag is legal; it is managed by the extension, + ** so if it's invalid, we have an implementation error. + */ + cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag); + if (!cx) { + cl->client->errorValue = tag; + *error = __glXBadContextTag; + return 0; + } + + if (!cx->isDirect) { + if (cx->drawPriv == NULL) { + /* + ** The drawable has vanished. It must be a window, because only + ** windows can be destroyed from under us; GLX pixmaps are + ** refcounted and don't go away until no one is using them. + */ + *error = __glXBadCurrentWindow; + return 0; + } + } + + if (cx == __glXLastContext) { + /* No need to re-bind */ + return cx; + } + + /* Make this context the current one for the GL. */ + if (!cx->isDirect) { + if (!(*cx->gc->exports.forceCurrent)((__GLcontext *)cx->gc)) { + /* Bind failed, and set the error code. Bummer */ + cl->client->errorValue = cx->id; + *error = __glXBadContextState; + return 0; + } + } + __glXLastContext = cx; + return cx; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** If we're expecting a glXRenderLarge request, this better be one. + */ + if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) { + client->errorValue = stuff->glxCode; + return __glXBadLargeRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +static int __glXSwapDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = (__GLXclientState *) __glXMalloc(sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + __glXMemset(cl, 0, sizeof(__GLXclientState)); + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c new file mode 100644 index 000000000..06dabddaa --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c @@ -0,0 +1,566 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.5 2001/01/30 07:01:22 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" + +#ifdef NXAGENT_SERVER + +#include "NXpicturestr.h" +#include "NXglyphstr.h" +#include "Render.h" + +#define PANIC +#define WARNING +#undef DEBUG +#undef TEST + +#endif + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 } +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +static int _GlyphSetPrivateAllocateIndex = 0; + +int +AllocateGlyphSetPrivateIndex (void) +{ + return _GlyphSetPrivateAllocateIndex++; +} + +void +ResetGlyphSetPrivateIndex (void) +{ + _GlyphSetPrivateAllocateIndex = 0; +} + +Bool +_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr) +{ + pointer *new; + + if (n > glyphSet->maxPrivate) { + if (glyphSet->devPrivates && + glyphSet->devPrivates != (pointer)(&glyphSet[1])) { + new = (pointer *) xrealloc (glyphSet->devPrivates, + (n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + } else { + new = (pointer *) xalloc ((n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + if (glyphSet->devPrivates) + memcpy (new, + glyphSet->devPrivates, + (glyphSet->maxPrivate + 1) * sizeof (pointer)); + } + glyphSet->devPrivates = new; + /* Zero out new, uninitialize privates */ + while (++glyphSet->maxPrivate < n) + glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0; + } + glyphSet->devPrivates[n] = ptr; + return TRUE; +} + +Bool +GlyphInit (ScreenPtr pScreen) +{ + return TRUE; +} + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) + { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) + { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) + { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || + memcmp (&compare->info, &glyph->info, compare->size) == 0)) + { + break; + } + if (!step) + { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +CARD32 +HashGlyph (GlyphPtr glyph) +{ + CARD32 *bits = (CARD32 *) &(glyph->info); + CARD32 hash; + int n = glyph->size / sizeof (CARD32); + + hash = 0; + while (n--) + hash ^= *bits++; + return hash; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef (GlyphPtr glyph, char *where) +{ + ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates (GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) + { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef (g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +void +FreeGlyph (GlyphPtr glyph, int format) +{ + CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) + { + GlyphRefPtr gr; + int i; + int first; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) + { + if (first != -1) + DuplicateRef (glyph, "FreeGlyph check"); + first = i; + } + + gr = FindGlyphRef (&globalGlyphs[format], + HashGlyph (glyph), TRUE, glyph); + if (gr - globalGlyphs[format].table != first) + DuplicateRef (glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + xfree (glyph); + } +} + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 hash; + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + hash = HashGlyph (glyph); + gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + xfree (glyph); + glyph = gr->glyph; + } + else + { + gr->glyph = glyph; + gr->signature = hash; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph (gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = 1; + + #endif + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph (glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +#ifdef NXAGENT_SERVER + +GlyphPtr FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr -> glyph; + + if (glyph == DeletedGlyph) + { + glyph = 0; + } + else if (gr -> corruptedGlyph == 1) + { + #ifdef DEBUG + fprintf(stderr, "FindGlyphRef: Going to synchronize the glyph [%p] for glyphset [%p].\n", + (void *) glyph, (void *) glyphSet); + #endif + + nxagentAddGlyphs(glyphSet, &id, &(glyph -> info), 1, + (CARD8*)(glyph + 1), glyph -> size - sizeof(xGlyphInfo)); + } + + return glyph; +} + +#else + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +#endif + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int fdepth) +{ + int size; + GlyphPtr glyph; + + size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); + glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof (xGlyphInfo); + glyph->info = *gi; + return glyph; +} + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); + if (!hash->table) + return FALSE; + memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + #ifdef NXAGENT_SERVER + + CARD32 c; + + #endif + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet (tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash (&newHash, hashSet)) + return FALSE; + if (hash->table) + { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) + { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) + { + s = hash->table[i].signature; + + #ifdef NXAGENT_SERVER + + c = hash->table[i].corruptedGlyph; + + #endif + + gr = FindGlyphRef (&newHash, s, global, glyph); + gr->signature = s; + gr->glyph = glyph; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = c; + + #endif + + ++newHash.tableEntries; + } + } + xfree (hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + int size; + + if (!globalGlyphs[fdepth].hashSet) + { + if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + + size = (sizeof (GlyphSetRec) + + (sizeof (pointer) * _GlyphSetPrivateAllocateIndex)); + glyphSet = xalloc (size); + if (!glyphSet) + return FALSE; + bzero((char *)glyphSet, size); + glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1; + if (_GlyphSetPrivateAllocateIndex) + glyphSet->devPrivates = (pointer)(&glyphSet[1]); + + if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) + { + xfree (glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet (pointer value, + XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) + { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) + { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph (glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) + { + xfree (globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); + xfree (table); + + if (glyphSet->devPrivates && + glyphSet->devPrivates != (pointer)(&glyphSet[1])) + xfree(glyphSet->devPrivates); + + xfree (glyphSet); + } + return Success; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.NX.original new file mode 100644 index 000000000..06dabddaa --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.NX.original @@ -0,0 +1,566 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.5 2001/01/30 07:01:22 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" + +#ifdef NXAGENT_SERVER + +#include "NXpicturestr.h" +#include "NXglyphstr.h" +#include "Render.h" + +#define PANIC +#define WARNING +#undef DEBUG +#undef TEST + +#endif + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 } +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +static int _GlyphSetPrivateAllocateIndex = 0; + +int +AllocateGlyphSetPrivateIndex (void) +{ + return _GlyphSetPrivateAllocateIndex++; +} + +void +ResetGlyphSetPrivateIndex (void) +{ + _GlyphSetPrivateAllocateIndex = 0; +} + +Bool +_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr) +{ + pointer *new; + + if (n > glyphSet->maxPrivate) { + if (glyphSet->devPrivates && + glyphSet->devPrivates != (pointer)(&glyphSet[1])) { + new = (pointer *) xrealloc (glyphSet->devPrivates, + (n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + } else { + new = (pointer *) xalloc ((n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + if (glyphSet->devPrivates) + memcpy (new, + glyphSet->devPrivates, + (glyphSet->maxPrivate + 1) * sizeof (pointer)); + } + glyphSet->devPrivates = new; + /* Zero out new, uninitialize privates */ + while (++glyphSet->maxPrivate < n) + glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0; + } + glyphSet->devPrivates[n] = ptr; + return TRUE; +} + +Bool +GlyphInit (ScreenPtr pScreen) +{ + return TRUE; +} + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) + { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) + { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) + { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || + memcmp (&compare->info, &glyph->info, compare->size) == 0)) + { + break; + } + if (!step) + { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +CARD32 +HashGlyph (GlyphPtr glyph) +{ + CARD32 *bits = (CARD32 *) &(glyph->info); + CARD32 hash; + int n = glyph->size / sizeof (CARD32); + + hash = 0; + while (n--) + hash ^= *bits++; + return hash; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef (GlyphPtr glyph, char *where) +{ + ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates (GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) + { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef (g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +void +FreeGlyph (GlyphPtr glyph, int format) +{ + CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) + { + GlyphRefPtr gr; + int i; + int first; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) + { + if (first != -1) + DuplicateRef (glyph, "FreeGlyph check"); + first = i; + } + + gr = FindGlyphRef (&globalGlyphs[format], + HashGlyph (glyph), TRUE, glyph); + if (gr - globalGlyphs[format].table != first) + DuplicateRef (glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + xfree (glyph); + } +} + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 hash; + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + hash = HashGlyph (glyph); + gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + xfree (glyph); + glyph = gr->glyph; + } + else + { + gr->glyph = glyph; + gr->signature = hash; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph (gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = 1; + + #endif + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph (glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +#ifdef NXAGENT_SERVER + +GlyphPtr FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr -> glyph; + + if (glyph == DeletedGlyph) + { + glyph = 0; + } + else if (gr -> corruptedGlyph == 1) + { + #ifdef DEBUG + fprintf(stderr, "FindGlyphRef: Going to synchronize the glyph [%p] for glyphset [%p].\n", + (void *) glyph, (void *) glyphSet); + #endif + + nxagentAddGlyphs(glyphSet, &id, &(glyph -> info), 1, + (CARD8*)(glyph + 1), glyph -> size - sizeof(xGlyphInfo)); + } + + return glyph; +} + +#else + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +#endif + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int fdepth) +{ + int size; + GlyphPtr glyph; + + size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); + glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof (xGlyphInfo); + glyph->info = *gi; + return glyph; +} + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); + if (!hash->table) + return FALSE; + memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + #ifdef NXAGENT_SERVER + + CARD32 c; + + #endif + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet (tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash (&newHash, hashSet)) + return FALSE; + if (hash->table) + { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) + { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) + { + s = hash->table[i].signature; + + #ifdef NXAGENT_SERVER + + c = hash->table[i].corruptedGlyph; + + #endif + + gr = FindGlyphRef (&newHash, s, global, glyph); + gr->signature = s; + gr->glyph = glyph; + + #ifdef NXAGENT_SERVER + + gr -> corruptedGlyph = c; + + #endif + + ++newHash.tableEntries; + } + } + xfree (hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + int size; + + if (!globalGlyphs[fdepth].hashSet) + { + if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + + size = (sizeof (GlyphSetRec) + + (sizeof (pointer) * _GlyphSetPrivateAllocateIndex)); + glyphSet = xalloc (size); + if (!glyphSet) + return FALSE; + bzero((char *)glyphSet, size); + glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1; + if (_GlyphSetPrivateAllocateIndex) + glyphSet->devPrivates = (pointer)(&glyphSet[1]); + + if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) + { + xfree (glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet (pointer value, + XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) + { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) + { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph (glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) + { + xfree (globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); + xfree (table); + + if (glyphSet->devPrivates && + glyphSet->devPrivates != (pointer)(&glyphSet[1])) + xfree(glyphSet->devPrivates); + + xfree (glyphSet); + } + return Success; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.X.original new file mode 100644 index 000000000..45c5dd975 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.X.original @@ -0,0 +1,478 @@ +/* + * $XFree86: xc/programs/Xserver/render/glyph.c,v 1.5 2001/01/30 07:01:22 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" +#include "glyphstr.h" + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 } +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +static int _GlyphSetPrivateAllocateIndex = 0; + +int +AllocateGlyphSetPrivateIndex (void) +{ + return _GlyphSetPrivateAllocateIndex++; +} + +void +ResetGlyphSetPrivateIndex (void) +{ + _GlyphSetPrivateAllocateIndex = 0; +} + +Bool +_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr) +{ + pointer *new; + + if (n > glyphSet->maxPrivate) { + if (glyphSet->devPrivates && + glyphSet->devPrivates != (pointer)(&glyphSet[1])) { + new = (pointer *) xrealloc (glyphSet->devPrivates, + (n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + } else { + new = (pointer *) xalloc ((n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + if (glyphSet->devPrivates) + memcpy (new, + glyphSet->devPrivates, + (glyphSet->maxPrivate + 1) * sizeof (pointer)); + } + glyphSet->devPrivates = new; + /* Zero out new, uninitialize privates */ + while (++glyphSet->maxPrivate < n) + glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0; + } + glyphSet->devPrivates[n] = ptr; + return TRUE; +} + +Bool +GlyphInit (ScreenPtr pScreen) +{ + return TRUE; +} + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) + { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) + { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) + { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || + memcmp (&compare->info, &glyph->info, compare->size) == 0)) + { + break; + } + if (!step) + { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +CARD32 +HashGlyph (GlyphPtr glyph) +{ + CARD32 *bits = (CARD32 *) &(glyph->info); + CARD32 hash; + int n = glyph->size / sizeof (CARD32); + + hash = 0; + while (n--) + hash ^= *bits++; + return hash; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef (GlyphPtr glyph, char *where) +{ + ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates (GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) + { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef (g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +void +FreeGlyph (GlyphPtr glyph, int format) +{ + CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) + { + GlyphRefPtr gr; + int i; + int first; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) + { + if (first != -1) + DuplicateRef (glyph, "FreeGlyph check"); + first = i; + } + + gr = FindGlyphRef (&globalGlyphs[format], + HashGlyph (glyph), TRUE, glyph); + if (gr - globalGlyphs[format].table != first) + DuplicateRef (glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + xfree (glyph); + } +} + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 hash; + + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + hash = HashGlyph (glyph); + gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); + if (gr->glyph && gr->glyph != DeletedGlyph) + { + xfree (glyph); + glyph = gr->glyph; + } + else + { + gr->glyph = glyph; + gr->signature = hash; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph (gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) + { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph (glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int fdepth) +{ + int size; + GlyphPtr glyph; + + size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); + glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof (xGlyphInfo); + glyph->info = *gi; + return glyph; +} + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); + if (!hash->table) + return FALSE; + memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet (tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash (&newHash, hashSet)) + return FALSE; + if (hash->table) + { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) + { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) + { + s = hash->table[i].signature; + gr = FindGlyphRef (&newHash, s, global, glyph); + gr->signature = s; + gr->glyph = glyph; + ++newHash.tableEntries; + } + } + xfree (hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates (hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + int size; + + if (!globalGlyphs[fdepth].hashSet) + { + if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + + size = (sizeof (GlyphSetRec) + + (sizeof (pointer) * _GlyphSetPrivateAllocateIndex)); + glyphSet = xalloc (size); + if (!glyphSet) + return FALSE; + bzero((char *)glyphSet, size); + glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1; + if (_GlyphSetPrivateAllocateIndex) + glyphSet->devPrivates = (pointer)(&glyphSet[1]); + + if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) + { + xfree (glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet (pointer value, + XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) + { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) + { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph (glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) + { + xfree (globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); + xfree (table); + + if (glyphSet->devPrivates && + glyphSet->devPrivates != (pointer)(&glyphSet[1])) + xfree(glyphSet->devPrivates); + + xfree (glyphSet); + } + return Success; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c new file mode 100644 index 000000000..3e105ac64 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c @@ -0,0 +1,241 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: glyphcurs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + +#include "../../fb/fb.h" +#include "Pixmaps.h" + +#ifndef True +#define True 1 +#endif + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(FontPtr pfont, unsigned ch, register CursorMetricPtr cm, unsigned char **ppbits) +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = fbCreatePixmap(pScreen, cm->width, cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + fbDestroyPixmap(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Created virtual pixmap at [%p] with width [%d] height [%d] depth [%d].\n", + (void *) ppix, cm->width, cm->height, 1); + #endif + + nxagentPixmapPriv(ppix) -> id = 0; + nxagentPixmapPriv(ppix) -> mid = 0; + nxagentPixmapPriv(ppix) -> isVirtual = True; + nxagentPixmapPriv(ppix) -> pRealPixmap = NULL; + nxagentPixmapPriv(ppix) -> pVirtualPixmap = NULL; + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + pGC->stateChanges |= GCFunction | GCForeground | GCFont; + pGC->alu = GXcopy; + + pGC->fgPixel = 0; + + pfont->refcnt++; + + if (pGC->font) + CloseFont(pGC->font, (Font)0); + + pGC->font = pfont; + + ValidateGC((DrawablePtr)ppix, pGC); + fbPolyFillRect((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + pGC->fgPixel = 1; + + pGC->stateChanges |= GCForeground; + + ValidateGC((DrawablePtr)ppix, pGC); + miPolyText16((DrawablePtr)ppix, pGC, (int)cm->xhot, (int)cm->yhot, (int)1, (unsigned short*)char2b); + fbGetImage((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + fbDestroyPixmap(ppix); + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Destroyed virtual pixmap at [%p].\n", + (void *) ppix); + #endif + + return Success; +} + + +Bool +CursorMetricsFromGlyph(register FontPtr pfont, unsigned ch, register CursorMetricPtr cm) +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.NX.original new file mode 100644 index 000000000..3e105ac64 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.NX.original @@ -0,0 +1,241 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: glyphcurs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + +#include "../../fb/fb.h" +#include "Pixmaps.h" + +#ifndef True +#define True 1 +#endif + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(FontPtr pfont, unsigned ch, register CursorMetricPtr cm, unsigned char **ppbits) +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = fbCreatePixmap(pScreen, cm->width, cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + fbDestroyPixmap(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Created virtual pixmap at [%p] with width [%d] height [%d] depth [%d].\n", + (void *) ppix, cm->width, cm->height, 1); + #endif + + nxagentPixmapPriv(ppix) -> id = 0; + nxagentPixmapPriv(ppix) -> mid = 0; + nxagentPixmapPriv(ppix) -> isVirtual = True; + nxagentPixmapPriv(ppix) -> pRealPixmap = NULL; + nxagentPixmapPriv(ppix) -> pVirtualPixmap = NULL; + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + pGC->stateChanges |= GCFunction | GCForeground | GCFont; + pGC->alu = GXcopy; + + pGC->fgPixel = 0; + + pfont->refcnt++; + + if (pGC->font) + CloseFont(pGC->font, (Font)0); + + pGC->font = pfont; + + ValidateGC((DrawablePtr)ppix, pGC); + fbPolyFillRect((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + pGC->fgPixel = 1; + + pGC->stateChanges |= GCForeground; + + ValidateGC((DrawablePtr)ppix, pGC); + miPolyText16((DrawablePtr)ppix, pGC, (int)cm->xhot, (int)cm->yhot, (int)1, (unsigned short*)char2b); + fbGetImage((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + fbDestroyPixmap(ppix); + + #ifdef TEST + fprintf(stderr, "ServerBitsFromGlyph: Destroyed virtual pixmap at [%p].\n", + (void *) ppix); + #endif + + return Success; +} + + +Bool +CursorMetricsFromGlyph(register FontPtr pfont, unsigned ch, register CursorMetricPtr cm) +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.X.original new file mode 100644 index 000000000..8f8adf5ce --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.X.original @@ -0,0 +1,194 @@ +/************************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* $Xorg: glyphcurs.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "resource.h" +#include "dix.h" +#include "cursorstr.h" +#include "opaque.h" +#include "servermd.h" + + +/* + get the bits out of the font in a portable way. to avoid +dealing with padding and such-like, we draw the glyph into +a bitmap, then read the bits out with GetImage, which +uses server-natural format. + since all screens return the same bitmap format, we'll just use +the first one we find. + the character origin lines up with the hotspot in the +cursor metrics. +*/ + +int +ServerBitsFromGlyph(FontPtr pfont, unsigned ch, register CursorMetricPtr cm, unsigned char **ppbits) +{ + register ScreenPtr pScreen; + register GCPtr pGC; + xRectangle rect; + PixmapPtr ppix; + long nby; + char *pbits; + ChangeGCVal gcval[3]; + unsigned char char2b[2]; + + /* turn glyph index into a protocol-format char2b */ + char2b[0] = (unsigned char)(ch >> 8); + char2b[1] = (unsigned char)(ch & 0xff); + + pScreen = screenInfo.screens[0]; + nby = BitmapBytePad(cm->width) * (long)cm->height; + pbits = (char *)xalloc(nby); + if (!pbits) + return BadAlloc; + /* zeroing the (pad) bits seems to help some ddx cursor handling */ + bzero(pbits, nby); + + ppix = (PixmapPtr)(*pScreen->CreatePixmap)(pScreen, cm->width, + cm->height, 1); + pGC = GetScratchGC(1, pScreen); + if (!ppix || !pGC) + { + if (ppix) + (*pScreen->DestroyPixmap)(ppix); + if (pGC) + FreeScratchGC(pGC); + xfree(pbits); + return BadAlloc; + } + + rect.x = 0; + rect.y = 0; + rect.width = cm->width; + rect.height = cm->height; + + /* fill the pixmap with 0 */ + gcval[0].val = GXcopy; + gcval[1].val = 0; + gcval[2].ptr = (pointer)pfont; + dixChangeGC(NullClient, pGC, GCFunction | GCForeground | GCFont, + NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyFillRect)((DrawablePtr)ppix, pGC, 1, &rect); + + /* draw the glyph */ + gcval[0].val = 1; + dixChangeGC(NullClient, pGC, GCForeground, NULL, gcval); + ValidateGC((DrawablePtr)ppix, pGC); + (*pGC->ops->PolyText16)((DrawablePtr)ppix, pGC, cm->xhot, cm->yhot, + 1, (unsigned short *)char2b); + (*pScreen->GetImage)((DrawablePtr)ppix, 0, 0, cm->width, cm->height, + XYPixmap, 1, pbits); + *ppbits = (unsigned char *)pbits; + FreeScratchGC(pGC); + (*pScreen->DestroyPixmap)(ppix); + return Success; +} + + +Bool +CursorMetricsFromGlyph(register FontPtr pfont, unsigned ch, register CursorMetricPtr cm) +{ + CharInfoPtr pci; + unsigned long nglyphs; + CARD8 chs[2]; + FontEncoding encoding; + + chs[0] = ch >> 8; + chs[1] = ch; + encoding = (FONTLASTROW(pfont) == 0) ? Linear16Bit : TwoD16Bit; + if (encoding == Linear16Bit) + { + if (ch < pfont->info.firstCol || pfont->info.lastCol < ch) + return FALSE; + } + else + { + if (chs[0] < pfont->info.firstRow || pfont->info.lastRow < chs[0]) + return FALSE; + if (chs[1] < pfont->info.firstCol || pfont->info.lastCol < chs[1]) + return FALSE; + } + (*pfont->get_glyphs) (pfont, 1, chs, encoding, &nglyphs, &pci); + if (nglyphs == 0) + return FALSE; + cm->width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + cm->height = pci->metrics.descent + pci->metrics.ascent; + if (pci->metrics.leftSideBearing > 0) + { + cm->width += pci->metrics.leftSideBearing; + cm->xhot = 0; + } + else + { + cm->xhot = -pci->metrics.leftSideBearing; + if (pci->metrics.rightSideBearing < 0) + cm->width -= pci->metrics.rightSideBearing; + } + if (pci->metrics.ascent < 0) + { + cm->height -= pci->metrics.ascent; + cm->yhot = 0; + } + else + { + cm->yhot = pci->metrics.ascent; + if (pci->metrics.descent < 0) + cm->height -= pci->metrics.descent; + } + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h new file mode 100644 index 000000000..0f30843d6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h @@ -0,0 +1,174 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.3 2000/11/20 07:13:13 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original glyphstr.h + * or symbols will be redefined. The code here adds a field + * to _GlyphSet. This should be done by defining a new type + * and casting when appropriate. + */ + +#ifndef _GLYPHSTR_H_ +#define _GLYPHSTR_H_ + +#include +#include "../../render/picture.h" +#include "screenint.h" + +#define GlyphFormat1 0 +#define GlyphFormat4 1 +#define GlyphFormat8 2 +#define GlyphFormat16 3 +#define GlyphFormat32 4 +#define GlyphFormatNum 5 + +typedef struct _Glyph { + CARD32 refcnt; + CARD32 size; /* info + bitmap */ + xGlyphInfo info; + /* bits follow */ +} GlyphRec, *GlyphPtr; + +typedef struct _GlyphRef { + CARD32 signature; + GlyphPtr glyph; + CARD16 corruptedGlyph; +} GlyphRefRec, *GlyphRefPtr; + +#define DeletedGlyph ((GlyphPtr) 1) + +typedef struct _GlyphHashSet { + CARD32 entries; + CARD32 size; + CARD32 rehash; +} GlyphHashSetRec, *GlyphHashSetPtr; + +typedef struct _GlyphHash { + GlyphRefPtr table; + GlyphHashSetPtr hashSet; + CARD32 tableEntries; +} GlyphHashRec, *GlyphHashPtr; + +typedef struct _GlyphSet { + CARD32 refcnt; + PictFormatPtr format; + int fdepth; + GlyphHashRec hash; + int maxPrivate; + pointer *devPrivates; + CARD32 remoteID; +} GlyphSetRec, *GlyphSetPtr; + +#define GlyphSetGetPrivate(pGlyphSet,n) \ + ((n) > (pGlyphSet)->maxPrivate ? \ + (pointer) 0 : \ + (pGlyphSet)->devPrivates[n]) + +#define GlyphSetSetPrivate(pGlyphSet,n,ptr) \ + ((n) > (pGlyphSet)->maxPrivate ? \ + _GlyphSetSetNewPrivate(pGlyphSet, n, ptr) : \ + ((((pGlyphSet)->devPrivates[n] = (ptr)) != 0) || TRUE)) + +typedef struct _GlyphList { + INT16 xOff; + INT16 yOff; + CARD8 len; + PictFormatPtr format; +} GlyphListRec, *GlyphListPtr; + +extern GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled); + +int +AllocateGlyphSetPrivateIndex (void); + +void +ResetGlyphSetPrivateIndex (void); + +Bool +_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr); + +Bool +GlyphInit (ScreenPtr pScreen); + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare); + +CARD32 +HashGlyph (GlyphPtr glyph); + +void +FreeGlyph (GlyphPtr glyph, int format); + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id); + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int format); + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet); + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global); + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change); + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format); + +int +FreeGlyphSet (pointer value, + XID gid); + + + +#endif /* _GLYPHSTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.NX.original new file mode 100644 index 000000000..0f30843d6 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.NX.original @@ -0,0 +1,174 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.3 2000/11/20 07:13:13 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original glyphstr.h + * or symbols will be redefined. The code here adds a field + * to _GlyphSet. This should be done by defining a new type + * and casting when appropriate. + */ + +#ifndef _GLYPHSTR_H_ +#define _GLYPHSTR_H_ + +#include +#include "../../render/picture.h" +#include "screenint.h" + +#define GlyphFormat1 0 +#define GlyphFormat4 1 +#define GlyphFormat8 2 +#define GlyphFormat16 3 +#define GlyphFormat32 4 +#define GlyphFormatNum 5 + +typedef struct _Glyph { + CARD32 refcnt; + CARD32 size; /* info + bitmap */ + xGlyphInfo info; + /* bits follow */ +} GlyphRec, *GlyphPtr; + +typedef struct _GlyphRef { + CARD32 signature; + GlyphPtr glyph; + CARD16 corruptedGlyph; +} GlyphRefRec, *GlyphRefPtr; + +#define DeletedGlyph ((GlyphPtr) 1) + +typedef struct _GlyphHashSet { + CARD32 entries; + CARD32 size; + CARD32 rehash; +} GlyphHashSetRec, *GlyphHashSetPtr; + +typedef struct _GlyphHash { + GlyphRefPtr table; + GlyphHashSetPtr hashSet; + CARD32 tableEntries; +} GlyphHashRec, *GlyphHashPtr; + +typedef struct _GlyphSet { + CARD32 refcnt; + PictFormatPtr format; + int fdepth; + GlyphHashRec hash; + int maxPrivate; + pointer *devPrivates; + CARD32 remoteID; +} GlyphSetRec, *GlyphSetPtr; + +#define GlyphSetGetPrivate(pGlyphSet,n) \ + ((n) > (pGlyphSet)->maxPrivate ? \ + (pointer) 0 : \ + (pGlyphSet)->devPrivates[n]) + +#define GlyphSetSetPrivate(pGlyphSet,n,ptr) \ + ((n) > (pGlyphSet)->maxPrivate ? \ + _GlyphSetSetNewPrivate(pGlyphSet, n, ptr) : \ + ((((pGlyphSet)->devPrivates[n] = (ptr)) != 0) || TRUE)) + +typedef struct _GlyphList { + INT16 xOff; + INT16 yOff; + CARD8 len; + PictFormatPtr format; +} GlyphListRec, *GlyphListPtr; + +extern GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled); + +int +AllocateGlyphSetPrivateIndex (void); + +void +ResetGlyphSetPrivateIndex (void); + +Bool +_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr); + +Bool +GlyphInit (ScreenPtr pScreen); + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare); + +CARD32 +HashGlyph (GlyphPtr glyph); + +void +FreeGlyph (GlyphPtr glyph, int format); + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id); + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int format); + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet); + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global); + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change); + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format); + +int +FreeGlyphSet (pointer value, + XID gid); + + + +#endif /* _GLYPHSTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.X.original new file mode 100644 index 000000000..f4777a248 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.X.original @@ -0,0 +1,148 @@ +/* + * $XFree86: xc/programs/Xserver/render/glyphstr.h,v 1.3 2000/11/20 07:13:13 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _GLYPHSTR_H_ +#define _GLYPHSTR_H_ + +#include +#include "picture.h" +#include "screenint.h" + +#define GlyphFormat1 0 +#define GlyphFormat4 1 +#define GlyphFormat8 2 +#define GlyphFormat16 3 +#define GlyphFormat32 4 +#define GlyphFormatNum 5 + +typedef struct _Glyph { + CARD32 refcnt; + CARD32 size; /* info + bitmap */ + xGlyphInfo info; + /* bits follow */ +} GlyphRec, *GlyphPtr; + +typedef struct _GlyphRef { + CARD32 signature; + GlyphPtr glyph; +} GlyphRefRec, *GlyphRefPtr; + +#define DeletedGlyph ((GlyphPtr) 1) + +typedef struct _GlyphHashSet { + CARD32 entries; + CARD32 size; + CARD32 rehash; +} GlyphHashSetRec, *GlyphHashSetPtr; + +typedef struct _GlyphHash { + GlyphRefPtr table; + GlyphHashSetPtr hashSet; + CARD32 tableEntries; +} GlyphHashRec, *GlyphHashPtr; + +typedef struct _GlyphSet { + CARD32 refcnt; + PictFormatPtr format; + int fdepth; + GlyphHashRec hash; + int maxPrivate; + pointer *devPrivates; +} GlyphSetRec, *GlyphSetPtr; + +#define GlyphSetGetPrivate(pGlyphSet,n) \ + ((n) > (pGlyphSet)->maxPrivate ? \ + (pointer) 0 : \ + (pGlyphSet)->devPrivates[n]) + +#define GlyphSetSetPrivate(pGlyphSet,n,ptr) \ + ((n) > (pGlyphSet)->maxPrivate ? \ + _GlyphSetSetNewPrivate(pGlyphSet, n, ptr) : \ + ((((pGlyphSet)->devPrivates[n] = (ptr)) != 0) || TRUE)) + +typedef struct _GlyphList { + INT16 xOff; + INT16 yOff; + CARD8 len; + PictFormatPtr format; +} GlyphListRec, *GlyphListPtr; + +extern GlyphHashRec globalGlyphs[GlyphFormatNum]; + +GlyphHashSetPtr +FindGlyphHashSet (CARD32 filled); + +int +AllocateGlyphSetPrivateIndex (void); + +void +ResetGlyphSetPrivateIndex (void); + +Bool +_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr); + +Bool +GlyphInit (ScreenPtr pScreen); + +GlyphRefPtr +FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare); + +CARD32 +HashGlyph (GlyphPtr glyph); + +void +FreeGlyph (GlyphPtr glyph, int format); + +void +AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id); + +Bool +DeleteGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +FindGlyph (GlyphSetPtr glyphSet, Glyph id); + +GlyphPtr +AllocateGlyph (xGlyphInfo *gi, int format); + +Bool +AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet); + +Bool +ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global); + +Bool +ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change); + +GlyphSetPtr +AllocateGlyphSet (int fdepth, PictFormatPtr format); + +int +FreeGlyphSet (pointer value, + XID gid); + + + +#endif /* _GLYPHSTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c new file mode 100644 index 000000000..af07fdcc2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c @@ -0,0 +1,979 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/mi/miexpose.c,v 1.6 2005/07/03 08:53:51 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9tsi Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/***************************************************************** + +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. + +******************************************************************/ + +/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_EVENTS +#include +#include + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include + +#include "globals.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifdef NXAGENT_SERVER + +#include "Windows.h" + +#endif + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + expBox.x1 = 0; + expBox.y1 = 0; + expBox.x2 = 0; + expBox.y2 = 0; + +#endif + + /* This prevents warning about pscr not being used. */ + pGC->pScreen = pscr = pGC->pScreen; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_NULL(pscr, prgnSrcClip); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_NULL(pscr, prgnDstClip); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + int scrnum = pWin->drawable.pScreen->myNum; + int x = 0, y = 0; + XID realWin = 0; + + if(!pWin->parent) { + x = panoramiXdataPtr[scrnum].x; + y = panoramiXdataPtr[scrnum].y; + pWin = WindowTable[0]; + realWin = pWin->drawable.id; + } else if (scrnum) { + PanoramiXRes *win; + win = PanoramiXFindIDByScrnum(XRT_WINDOW, + pWin->drawable.id, scrnum); + if(!win) { + DEALLOCATE_LOCAL(pEvent); + return; + } + realWin = win->info[0].id; + pWin = LookupIDByType(realWin, RT_WINDOW); + } + if(x || y || scrnum) + for (i = 0; i < numRects; i++) { + pEvent[i].u.expose.window = realWin; + pEvent[i].u.expose.x += x; + pEvent[i].u.expose.y += y; + } + } +#endif + + DeliverEvents(pWin, pEvent, numRects, NullWindow); + + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ +#ifdef NXAGENT_SERVER + + int total; + +#endif + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } +#ifdef NXAGENT_SERVER + + /* + * If the number of rectangles is greater + * than 4, let the function decide. + */ + + total = REGION_NUM_RECTS(exposures); + + if (clientInterested && exposures && (total > RECTLIMIT || + (total > 4 && nxagentExtentsPredicate(total) == 1))) +#else + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) +#endif + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC ( + pointer value, + XID id) +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; + + return 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + prgnWin.extents.x1 = 0; + prgnWin.extents.y1 = 0; + prgnWin.extents.x2 = 0; + prgnWin.extents.y2 = 0; + + prgnWin.data = NULL; + + oldCorner.x = 0; + oldCorner.y = 0; + +#endif + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +void +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.NX.original new file mode 100644 index 000000000..af07fdcc2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.NX.original @@ -0,0 +1,979 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/mi/miexpose.c,v 1.6 2005/07/03 08:53:51 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9tsi Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/***************************************************************** + +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. + +******************************************************************/ + +/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_EVENTS +#include +#include + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include + +#include "globals.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifdef NXAGENT_SERVER + +#include "Windows.h" + +#endif + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + expBox.x1 = 0; + expBox.y1 = 0; + expBox.x2 = 0; + expBox.y2 = 0; + +#endif + + /* This prevents warning about pscr not being used. */ + pGC->pScreen = pscr = pGC->pScreen; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_NULL(pscr, prgnSrcClip); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_NULL(pscr, prgnDstClip); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + int scrnum = pWin->drawable.pScreen->myNum; + int x = 0, y = 0; + XID realWin = 0; + + if(!pWin->parent) { + x = panoramiXdataPtr[scrnum].x; + y = panoramiXdataPtr[scrnum].y; + pWin = WindowTable[0]; + realWin = pWin->drawable.id; + } else if (scrnum) { + PanoramiXRes *win; + win = PanoramiXFindIDByScrnum(XRT_WINDOW, + pWin->drawable.id, scrnum); + if(!win) { + DEALLOCATE_LOCAL(pEvent); + return; + } + realWin = win->info[0].id; + pWin = LookupIDByType(realWin, RT_WINDOW); + } + if(x || y || scrnum) + for (i = 0; i < numRects; i++) { + pEvent[i].u.expose.window = realWin; + pEvent[i].u.expose.x += x; + pEvent[i].u.expose.y += y; + } + } +#endif + + DeliverEvents(pWin, pEvent, numRects, NullWindow); + + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ +#ifdef NXAGENT_SERVER + + int total; + +#endif + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } +#ifdef NXAGENT_SERVER + + /* + * If the number of rectangles is greater + * than 4, let the function decide. + */ + + total = REGION_NUM_RECTS(exposures); + + if (clientInterested && exposures && (total > RECTLIMIT || + (total > 4 && nxagentExtentsPredicate(total) == 1))) +#else + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) +#endif + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC ( + pointer value, + XID id) +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; + + return 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + +#ifdef NXAGENT_SERVER + + /* + * Set the elements reported by the compiler + * as uninitialized. + */ + + prgnWin.extents.x1 = 0; + prgnWin.extents.y1 = 0; + prgnWin.extents.x2 = 0; + prgnWin.extents.y2 = 0; + + prgnWin.data = NULL; + + oldCorner.x = 0; + oldCorner.y = 0; + +#endif + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +void +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.X.original new file mode 100644 index 000000000..9a0bd06b5 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.X.original @@ -0,0 +1,905 @@ +/* $XdotOrg: xc/programs/Xserver/mi/miexpose.c,v 1.6 2005/07/03 08:53:51 daniels Exp $ */ +/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.9tsi Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/***************************************************************** + +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. + +******************************************************************/ + +/* $Xorg: miexpose.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_EVENTS +#include +#include + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include + +#include "globals.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + + /* This prevents warning about pscr not being used. */ + pGC->pScreen = pscr = pGC->pScreen; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_NULL(pscr, prgnSrcClip); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_NULL(pscr, prgnDstClip); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + int scrnum = pWin->drawable.pScreen->myNum; + int x = 0, y = 0; + XID realWin = 0; + + if(!pWin->parent) { + x = panoramiXdataPtr[scrnum].x; + y = panoramiXdataPtr[scrnum].y; + pWin = WindowTable[0]; + realWin = pWin->drawable.id; + } else if (scrnum) { + PanoramiXRes *win; + win = PanoramiXFindIDByScrnum(XRT_WINDOW, + pWin->drawable.id, scrnum); + if(!win) { + DEALLOCATE_LOCAL(pEvent); + return; + } + realWin = win->info[0].id; + pWin = LookupIDByType(realWin, RT_WINDOW); + } + if(x || y || scrnum) + for (i = 0; i < numRects; i++) { + pEvent[i].u.expose.window = realWin; + pEvent[i].u.expose.x += x; + pEvent[i].u.expose.y += y; + } + } +#endif + + DeliverEvents(pWin, pEvent, numRects, NullWindow); + + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC ( + pointer value, + XID id) +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; + + return 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +void +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c new file mode 100644 index 000000000..6ad60223f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c @@ -0,0 +1,318 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.4 2000/11/20 07:13:13 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifdef NXAGENT_SERVER + +#include "Render.h" + +#endif + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + PixmapPtr pPixmap = 0; + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents; + CARD32 component_alpha; + + #ifdef NXAGENT_SERVER + + /* + * Get rid of the warning. + */ + + extents.x1 = 0; + extents.y1 = 0; + + #endif + + if (maskFormat) + { + GCPtr pGC; + xRectangle rect; + + #ifdef NXAGENT_SERVER + + if (nxagentGlyphsExtents != NullBox) + { + memcpy(&extents, nxagentGlyphsExtents, sizeof(BoxRec)); + } + else + { + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents (nlist, list, glyphs, &extents); + + memcpy(nxagentGlyphsExtents, &extents, sizeof(BoxRec)); + } + + #else + + miGlyphExtents (nlist, list, glyphs, &extents); + + #endif + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); + + if (!pMaskPixmap) + return; + + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture (0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + + if (!pMask) + { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); + ValidateGC (&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + x = -extents.x1; + y = -extents.y1; + } + else + { + pMask = pDst; + x = 0; + y = 0; + } + pPicture = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + + while (n--) + { + glyph = *glyphs++; + if (!pPicture) + { + pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, + list->format->depth, + list->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + component_alpha = NeedsComponent(list->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, list->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + + #ifdef NXAGENT_SERVER + + /* + * The following line fixes a problem with glyphs that appeared + * as clipped. It was a side effect due the validate function + * "ValidatePicture" that makes a check on the Drawable serial + * number instead of the picture serial number, failing thus + * the clip mask update. + */ + + pPicture->pDrawable->serialNumber = NEXT_SERIAL_NUMBER; + + #endif + + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (maskFormat) + { + CompositePicture (PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + else + { + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + + list++; + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + pPicture = 0; + pPixmap = 0; + } + } + if (maskFormat) + { + x = extents.x1; + y = extents.y1; + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + + FreePicture ((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } + +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.NX.original new file mode 100644 index 000000000..6ad60223f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.NX.original @@ -0,0 +1,318 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.4 2000/11/20 07:13:13 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifdef NXAGENT_SERVER + +#include "Render.h" + +#endif + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + PixmapPtr pPixmap = 0; + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents; + CARD32 component_alpha; + + #ifdef NXAGENT_SERVER + + /* + * Get rid of the warning. + */ + + extents.x1 = 0; + extents.y1 = 0; + + #endif + + if (maskFormat) + { + GCPtr pGC; + xRectangle rect; + + #ifdef NXAGENT_SERVER + + if (nxagentGlyphsExtents != NullBox) + { + memcpy(&extents, nxagentGlyphsExtents, sizeof(BoxRec)); + } + else + { + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents (nlist, list, glyphs, &extents); + + memcpy(nxagentGlyphsExtents, &extents, sizeof(BoxRec)); + } + + #else + + miGlyphExtents (nlist, list, glyphs, &extents); + + #endif + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); + + if (!pMaskPixmap) + return; + + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture (0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + + if (!pMask) + { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); + ValidateGC (&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + x = -extents.x1; + y = -extents.y1; + } + else + { + pMask = pDst; + x = 0; + y = 0; + } + pPicture = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + + while (n--) + { + glyph = *glyphs++; + if (!pPicture) + { + pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, + list->format->depth, + list->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + component_alpha = NeedsComponent(list->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, list->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + + #ifdef NXAGENT_SERVER + + /* + * The following line fixes a problem with glyphs that appeared + * as clipped. It was a side effect due the validate function + * "ValidatePicture" that makes a check on the Drawable serial + * number instead of the picture serial number, failing thus + * the clip mask update. + */ + + pPicture->pDrawable->serialNumber = NEXT_SERIAL_NUMBER; + + #endif + + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (maskFormat) + { + CompositePicture (PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + else + { + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + + list++; + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + pPicture = 0; + pPixmap = 0; + } + } + if (maskFormat) + { + x = extents.x1; + y = extents.y1; + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + + FreePicture ((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } + +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.X.original new file mode 100644 index 000000000..237ec13a4 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.X.original @@ -0,0 +1,243 @@ +/* + * $XFree86: xc/programs/Xserver/render/miglyph.c,v 1.4 2000/11/20 07:13:13 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +void +miGlyphExtents (int nlist, + GlyphListPtr list, + GlyphPtr *glyphs, + BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) + { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + PixmapPtr pPixmap = 0; + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents; + CARD32 component_alpha; + + if (maskFormat) + { + GCPtr pGC; + xRectangle rect; + + miGlyphExtents (nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, maskFormat->depth); + if (!pMaskPixmap) + return; + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture (0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pMask) + { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); + ValidateGC (&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + x = -extents.x1; + y = -extents.y1; + } + else + { + pMask = pDst; + x = 0; + y = 0; + } + pPicture = 0; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) + { + glyph = *glyphs++; + if (!pPicture) + { + pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height, + list->format->depth, + list->format->depth, + 0, (pointer) (glyph + 1)); + if (!pPixmap) + return; + component_alpha = NeedsComponent(list->format->format); + pPicture = CreatePicture (0, &pPixmap->drawable, list->format, + CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pPicture) + { + FreeScratchPixmapHeader (pPixmap); + return; + } + } + (*pScreen->ModifyPixmapHeader) (pPixmap, + glyph->info.width, glyph->info.height, + 0, 0, -1, (pointer) (glyph + 1)); + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (maskFormat) + { + CompositePicture (PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + else + { + CompositePicture (op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + } + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + if (pPicture) + { + FreeScratchPixmapHeader (pPixmap); + FreePicture ((pointer) pPicture, 0); + pPicture = 0; + pPixmap = 0; + } + } + if (maskFormat) + { + x = extents.x1; + y = extents.y1; + CompositePicture (op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, + 0, 0, + x, y, + width, height); + FreePicture ((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c new file mode 100644 index 000000000..e08f5e45f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c @@ -0,0 +1,233 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.8 2002/09/03 19:28:28 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifdef NXAGENT_SERVER + +#include "Render.h" + +#endif + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) + { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC (&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +static xFixed +miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), + miLineFixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), + miLineFixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + } +} + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + /* + * Check for solid alpha add + */ + if (op == PictOpAdd && miIsSolidAlpha (pSrc)) + { + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); + } + else if (maskFormat) + { + PicturePtr pPicture; + BoxRec bounds; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + #ifdef NXAGENT_SERVER + + if (nxagentTrapezoidExtents != NullBox) + { + memcpy(&bounds, nxagentTrapezoidExtents, sizeof(BoxRec)); + } + else + { + nxagentTrapezoidExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miTrapezoidBounds (ntrap, traps, &bounds); + + memcpy(nxagentTrapezoidExtents, &bounds, sizeof(BoxRec)); + } + + #else + + miTrapezoidBounds (ntrap, traps, &bounds); + + #endif + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + else + { + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + for (; ntrap; ntrap--, traps++) + miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.NX.original new file mode 100644 index 000000000..e08f5e45f --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.NX.original @@ -0,0 +1,233 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.8 2002/09/03 19:28:28 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifdef NXAGENT_SERVER + +#include "Render.h" + +#endif + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) + { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC (&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +static xFixed +miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), + miLineFixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), + miLineFixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + } +} + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + /* + * Check for solid alpha add + */ + if (op == PictOpAdd && miIsSolidAlpha (pSrc)) + { + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); + } + else if (maskFormat) + { + PicturePtr pPicture; + BoxRec bounds; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + #ifdef NXAGENT_SERVER + + if (nxagentTrapezoidExtents != NullBox) + { + memcpy(&bounds, nxagentTrapezoidExtents, sizeof(BoxRec)); + } + else + { + nxagentTrapezoidExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miTrapezoidBounds (ntrap, traps, &bounds); + + memcpy(nxagentTrapezoidExtents, &bounds, sizeof(BoxRec)); + } + + #else + + miTrapezoidBounds (ntrap, traps, &bounds); + + #endif + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + else + { + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + for (; ntrap; ntrap--, traps++) + miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.X.original new file mode 100644 index 000000000..be1712420 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.X.original @@ -0,0 +1,190 @@ +/* + * $XFree86: xc/programs/Xserver/render/mitrap.c,v 1.8 2002/09/03 19:28:28 keithp Exp $ + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +PicturePtr +miCreateAlphaPicture (ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, + CARD16 width, + CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) + { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth); + if (!pPixmap) + return 0; + pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC (&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC (pGC); + pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +static xFixed +miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) +{ + xFixed dx = l->p2.x - l->p1.x; + xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; + xFixed dy = l->p2.y - l->p1.y; + if (ceil) + ex += (dy - 1); + return l->p1.x + (xFixed) (ex / dy); +} + +void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) +{ + box->y1 = MAXSHORT; + box->y2 = MINSHORT; + box->x1 = MAXSHORT; + box->x2 = MINSHORT; + for (; ntrap; ntrap--, traps++) + { + INT16 x1, y1, x2, y2; + + if (!xTrapezoidValid(traps)) + continue; + y1 = xFixedToInt (traps->top); + if (y1 < box->y1) + box->y1 = y1; + + y2 = xFixedToInt (xFixedCeil (traps->bottom)); + if (y2 > box->y2) + box->y2 = y2; + + x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), + miLineFixedX (&traps->left, traps->bottom, FALSE))); + if (x1 < box->x1) + box->x1 = x1; + + x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), + miLineFixedX (&traps->right, traps->bottom, TRUE)))); + if (x2 > box->x2) + box->x2 = x2; + } +} + +void +miTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + /* + * Check for solid alpha add + */ + if (op == PictOpAdd && miIsSolidAlpha (pSrc)) + { + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); + } + else if (maskFormat) + { + PicturePtr pPicture; + BoxRec bounds; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + miTrapezoidBounds (ntrap, traps, &bounds); + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); + } + else + { + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + for (; ntrap; ntrap--, traps++) + miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c new file mode 100644 index 000000000..1731e0753 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c @@ -0,0 +1,1222 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/mi/miwindow.c,v 1.9tsi Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: miwindow.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "regionstr.h" +#include "region.h" +#include "mi.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" + +void +miClearToBackground(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x,y; + int w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + + /* compute everything using ints to avoid overflow */ + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + extents = &pWin->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pWin->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); + if (generateExposures) + (*pScreen->WindowExposures)(pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +/* + * For SaveUnders using backing-store. The idea is that when a window is mapped + * with saveUnder set TRUE, any windows it obscures will have its backing + * store turned on setting the DIXsaveUnder bit, + * The backing-store code must be written to allow for this + */ + +/*- + *----------------------------------------------------------------------- + * miCheckSubSaveUnder -- + * Check all the inferiors of a window for coverage by saveUnder + * windows. Called from ChangeSaveUnder and CheckSaveUnder. + * This code is very inefficient. + * + * Results: + * TRUE if any windows need to have backing-store removed. + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +static Bool +miCheckSubSaveUnder( + register WindowPtr pParent, /* Parent to check */ + WindowPtr pFirst, /* first reconfigured window */ + RegionPtr pRegion) /* Initial area obscured by saveUnder */ +{ + register WindowPtr pChild; /* Current child */ + register ScreenPtr pScreen; /* Screen to use */ + RegionRec SubRegion; /* Area of children obscured */ + Bool res = FALSE; /* result */ + Bool subInited=FALSE;/* SubRegion initialized */ + + pScreen = pParent->drawable.pScreen; + if ( (pChild = pParent->firstChild) ) + { + /* + * build region above first changed window + */ + + for (; pChild != pFirst; pChild = pChild->nextSib) + if (pChild->viewable && pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + + /* + * check region below and including first changed window + */ + + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + { + /* + * don't save under nephew/niece windows; + * use a separate region + */ + + if (pChild->firstChild) + { + if (!subInited) + { + REGION_NULL(pScreen, &SubRegion); + subInited = TRUE; + } + REGION_COPY(pScreen, &SubRegion, pRegion); + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + &SubRegion); + } + else + { + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + pRegion); + } + + if (pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + } + } + + if (subInited) + REGION_UNINIT(pScreen, &SubRegion); + } + + /* + * Check the state of this window. DIX save unders are + * enabled for viewable windows with some client expressing + * exposure interest and which intersect the save under region + */ + + if (pParent->viewable && + ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && + REGION_NOTEMPTY(pScreen, &pParent->borderSize) && + RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, + &pParent->borderSize)) != rgnOUT) + { + if (!pParent->DIXsaveUnder) + { + pParent->DIXsaveUnder = TRUE; + (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); + } + } + else + { + if (pParent->DIXsaveUnder) + { + res = TRUE; + pParent->DIXsaveUnder = FALSE; + } + } + return res; +} + + +/*- + *----------------------------------------------------------------------- + * miChangeSaveUnder -- + * Change the save-under state of a tree of windows. Called when + * a window with saveUnder TRUE is mapped/unmapped/reconfigured. + * + * Results: + * TRUE if any windows need to have backing-store removed (which + * means that PostChangeSaveUnder needs to be called later to + * finish the job). + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +Bool +miChangeSaveUnder(pWin, first) + register WindowPtr pWin; + WindowPtr first; /* First window to check. + * Used when pWin was restacked */ +{ + RegionRec rgn; /* Area obscured by saveUnder windows */ + register ScreenPtr pScreen; + Bool res; + + if (!deltaSaveUndersViewable && !numSaveUndersViewable) + return FALSE; + numSaveUndersViewable += deltaSaveUndersViewable; + deltaSaveUndersViewable = 0; + pScreen = pWin->drawable.pScreen; + REGION_NULL(pScreen, &rgn); + res = miCheckSubSaveUnder (pWin->parent, + pWin->saveUnder ? first : pWin->nextSib, + &rgn); + REGION_UNINIT(pScreen, &rgn); + return res; +} + +/*- + *----------------------------------------------------------------------- + * miPostChangeSaveUnder -- + * Actually turn backing-store off for those windows that no longer + * need to have it on. + * + * Results: + * None. + * + * Side Effects: + * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those + * windows affected. + * + *----------------------------------------------------------------------- + */ +void +miPostChangeSaveUnder(pWin, pFirst) + WindowPtr pWin; + WindowPtr pFirst; +{ + register WindowPtr pParent, pChild; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + if (!(pParent = pWin->parent)) + return; + ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; + if (!pParent->DIXsaveUnder && + (pParent->backingStore == NotUseful) && pParent->backStorage) + (*ChangeWindowAttributes)(pParent, CWBackingStore); + if (!(pChild = pFirst)) + return; + while (1) + { + if (!pChild->DIXsaveUnder && + (pChild->backingStore == NotUseful) && pChild->backStorage) + (*ChangeWindowAttributes)(pChild, CWBackingStore); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib) + { + pChild = pChild->parent; + if (pChild == pParent) + return; + } + pChild = pChild->nextSib; + } +} + +void +miMarkWindow(pWin) + register WindowPtr pWin; +{ + register ValidatePtr val; + + if (pWin->valdata) + return; + val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); + val->before.oldAbsCorner.x = pWin->drawable.x; + val->before.oldAbsCorner.y = pWin->drawable.y; + val->before.borderVisible = NullRegion; + val->before.resized = FALSE; + pWin->valdata = val; +} + +Bool +miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) + WindowPtr pWin; + WindowPtr pFirst; + WindowPtr *ppLayerWin; +{ + register BoxPtr box; + register WindowPtr pChild, pLast; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + + /* 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 ( (pChild = pFirst) ) + { + box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); + pLast = pChild->parent->lastChild; + while (1) + { + if (pChild->viewable) + { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) + { + (* MarkWindow)(pChild); + anyMarked = TRUE; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + } + while (!pChild->nextSib && (pChild != pLast)) + pChild = pChild->parent; + if (pChild == pLast) + break; + pChild = pChild->nextSib; + } + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + return anyMarked; +} + +/***** + * miHandleValidateExposures(pWin) + * starting at pWin, draw background in any windows that have exposure + * regions, translate the regions, restore any backing store, + * and then send any regions still exposed to the client + *****/ +void +miHandleValidateExposures(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + register ValidatePtr val; + ScreenPtr pScreen; + WindowExposuresProcPtr WindowExposures; + + pScreen = pWin->drawable.pScreen; + + pChild = pWin; + WindowExposures = pChild->drawable.pScreen->WindowExposures; + while (1) + { + if ( (val = pChild->valdata) ) + { + if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) + (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, + &val->after.borderExposed, + PW_BORDER); + REGION_UNINIT(pScreen, &val->after.borderExposed); + (*WindowExposures)(pChild, &val->after.exposed, NullRegion); + REGION_UNINIT(pScreen, &val->after.exposed); + xfree(val); + pChild->valdata = (ValidatePtr)NULL; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +void +miMoveWindow(pWin, x, y, pNextSib, kind) + register WindowPtr pWin; + int x,y; + WindowPtr pNextSib; + VTKind kind; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + short bw; + RegionPtr oldRegion = NULL; + DDXPointRec oldpt; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr windowToValidate; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return ; + pScreen = pWin->drawable.pScreen; + bw = wBorderWidth (pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) + { + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->borderClip); + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + } + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + SetWinSize (pWin); + SetBorderSize (pWin); + + (*pScreen->PositionWindow)(pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) + { + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, windowToValidate, (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, pLayerWin, (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); + (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); + REGION_DESTROY(pScreen, oldRegion); + /* XXX need to retile border if ParentRelative origin */ + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + + +/* + * pValid is a region of the screen which has been + * successfully copied -- recomputed exposed regions for affected windows + */ + +static int +miRecomputeExposures ( + register WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + register ScreenPtr pScreen; + RegionPtr pValid = (RegionPtr)value; + + if (pWin->valdata) + { + pScreen = pWin->drawable.pScreen; + /* + * compute exposed regions of this window + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->clipList, pValid); + /* + * compute exposed regions of the border + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid); + return WT_WALKCHILDREN; + } + return WT_NOMATCH; +} + +void +miSlideAndSizeWindow(pWin, x, y, w, h, pSib) + register WindowPtr pWin; + int x,y; + unsigned int w, h; + WindowPtr pSib; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + unsigned short width = pWin->drawable.width, + height = pWin->drawable.height; + short oldx = pWin->drawable.x, + oldy = pWin->drawable.y; + int bw = wBorderWidth (pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion = NULL; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr pFirstChange; + register WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + register unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion = NULL; + RegionPtr destClip; /* portions of destination already written */ + RegionPtr oldWinClip = NULL; /* old clip list for window */ + RegionPtr borderVisible = NullRegion; /* visible area of the border */ + RegionPtr bsExposed = NullRegion; /* backing store exposures */ + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return ; + + pScreen = pWin->drawable.pScreen; + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) + { + anyMarked = FALSE; + /* + * save the visible region of the window + */ + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->winSize); + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = (RegionPtr) NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + g = pChild->winGravity; + if (g != UnmapGravity) + { + if (!gravitate[g]) + gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); + REGION_UNION(pScreen, gravitate[g], + gravitate[g], &pChild->borderClip); + } + else + { + UnmapWindow(pChild, TRUE); + anyMarked = TRUE; + } + } + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + + oldWinClip = NULL; + if (pWin->bitGravity != ForgetGravity) + { + oldWinClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldWinClip, &pWin->clipList); + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder (pWin)) + { + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) + { + if (shrunk || moved) + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, + &pWin->winSize); + else + REGION_COPY(pScreen, borderVisible, + &pWin->borderClip); + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize (pWin); + SetBorderSize (pWin); + + dw = (int)w - (int)width; + dh = (int)h - (int)height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow)(pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + pRegion = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->backStorage) + REGION_COPY(pScreen, pRegion, &pWin->clipList); + + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + + if (pWin->valdata) + { + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); + } + + GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pRegion = &pWin->clipList; /* a convenient empty region */ + if (pWin->bitGravity == ForgetGravity) + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, NullRegion, oldx, oldy); + else + { + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, nx - x, ny - y, pRegion, oldx, oldy); + } + } + + if (WasViewable) + { + /* avoid the border */ + if (HasBorder (pWin)) + { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) + { + REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip) + { + /* + * clip to new clipList + */ + REGION_COPY(pScreen, pRegion, oldWinClip); + REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); + REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) + { + if (gravitate[g]) + REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, + gravitate[g]); + } + REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else + { + REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); + REGION_DESTROY(pScreen, oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = NULL; + + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); + + /* clip to not overwrite already copied areas */ + + if (destClip) { + REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); + REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); + REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y +#ifdef COMPOSITE + || pWin->redirectDraw +#endif + ) + { + (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); + } + + /* remove any overwritten bits from the remaining useful bits */ + + REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->winGravity != g) + continue; + REGION_INTERSECT(pScreen, pRegion, + &pChild->borderClip, gravitate[g]); + TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (!destClip) + destClip = gravitate[g]; + else + { + REGION_UNION(pScreen, destClip, destClip, gravitate[g]); + REGION_DESTROY(pScreen, gravitate[g]); + } + } + + REGION_DESTROY(pScreen, oldRegion); + REGION_DESTROY(pScreen, pRegion); + if (destClip) + REGION_DESTROY(pScreen, destClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, + VTOther); + } + else if (bsExposed) + { + (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (pWin->realized) + WindowsRestructured (); +} + +WindowPtr +miGetLayerWindow(pWin) + WindowPtr pWin; +{ + return pWin->firstChild; +} + +#ifdef SHAPE +/****** + * + * miSetShape + * The border/window shape has changed. Recompute winSize/borderSize + * and send appropriate exposure events + */ + +void +miSetShape(pWin) + register WindowPtr pWin; +{ + Bool WasViewable = (Bool)(pWin->viewable); + register ScreenPtr pScreen = pWin->drawable.pScreen; + Bool anyMarked = FALSE; + RegionPtr pOldClip = NULL, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); +#ifdef NXAGENT_SERVER + + /* + * We got a few, rare, segfaults here after having + * started using the backing store. It may be a + * different bug but miChangeSaveUnder() calls mi- + * CheckSubSaveUnder() that, in turn, can change + * the backing store attribute of the window. This + * means that we may try to destroy the region + * even if it was not created at the beginning of + * this function as, at the time, the backing store + * was off. miCheckSubSaveUnder() appear to get a + * pointer to the parent, so maybe doesn't change + * the attribute of the window itself. This is to + * be better investigated. + */ + + if (WasViewable && pOldClip) + REGION_DESTROY(pScreen, pOldClip); +#else + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); +#endif + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + CheckCursorConfinement(pWin); +} +#endif + +/* Keeps the same inside(!) origin */ + +void +miChangeBorderWidth(pWin, width) + register WindowPtr pWin; + unsigned int width; +{ + int oldwidth; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + Bool WasViewable = (Bool)(pWin->viewable); + Bool HadBorder; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + oldwidth = wBorderWidth (pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + if (WasViewable && width < oldwidth) + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + + pWin->borderWidth = width; + SetBorderSize (pWin); + + if (WasViewable) + { + if (width > oldwidth) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + /* + * save the old border visible region to correctly compute + * borderExposed. + */ + if (pWin->valdata && HadBorder) + { + RegionPtr borderVisible; + borderVisible = REGION_CREATE(pScreen, NULL, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, + VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +miMarkUnrealizedWindow(pChild, pWin, fromConfigure) + WindowPtr pChild; + WindowPtr pWin; + Bool fromConfigure; +{ + if ((pChild != pWin) || fromConfigure) + { + REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); + REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); + } +} + +void +miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) +{ + ScreenPtr pScreen; + WindowPtr pChild; + + pScreen = pWin->drawable.pScreen; + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->drawable.depth == depth) + REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); + + if (pChild->firstChild) + miSegregateChildren(pChild, pReg, depth); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.NX.original new file mode 100644 index 000000000..1731e0753 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.NX.original @@ -0,0 +1,1222 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/mi/miwindow.c,v 1.9tsi Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: miwindow.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "regionstr.h" +#include "region.h" +#include "mi.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" + +void +miClearToBackground(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x,y; + int w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + + /* compute everything using ints to avoid overflow */ + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + extents = &pWin->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pWin->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); + if (generateExposures) + (*pScreen->WindowExposures)(pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +/* + * For SaveUnders using backing-store. The idea is that when a window is mapped + * with saveUnder set TRUE, any windows it obscures will have its backing + * store turned on setting the DIXsaveUnder bit, + * The backing-store code must be written to allow for this + */ + +/*- + *----------------------------------------------------------------------- + * miCheckSubSaveUnder -- + * Check all the inferiors of a window for coverage by saveUnder + * windows. Called from ChangeSaveUnder and CheckSaveUnder. + * This code is very inefficient. + * + * Results: + * TRUE if any windows need to have backing-store removed. + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +static Bool +miCheckSubSaveUnder( + register WindowPtr pParent, /* Parent to check */ + WindowPtr pFirst, /* first reconfigured window */ + RegionPtr pRegion) /* Initial area obscured by saveUnder */ +{ + register WindowPtr pChild; /* Current child */ + register ScreenPtr pScreen; /* Screen to use */ + RegionRec SubRegion; /* Area of children obscured */ + Bool res = FALSE; /* result */ + Bool subInited=FALSE;/* SubRegion initialized */ + + pScreen = pParent->drawable.pScreen; + if ( (pChild = pParent->firstChild) ) + { + /* + * build region above first changed window + */ + + for (; pChild != pFirst; pChild = pChild->nextSib) + if (pChild->viewable && pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + + /* + * check region below and including first changed window + */ + + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + { + /* + * don't save under nephew/niece windows; + * use a separate region + */ + + if (pChild->firstChild) + { + if (!subInited) + { + REGION_NULL(pScreen, &SubRegion); + subInited = TRUE; + } + REGION_COPY(pScreen, &SubRegion, pRegion); + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + &SubRegion); + } + else + { + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + pRegion); + } + + if (pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + } + } + + if (subInited) + REGION_UNINIT(pScreen, &SubRegion); + } + + /* + * Check the state of this window. DIX save unders are + * enabled for viewable windows with some client expressing + * exposure interest and which intersect the save under region + */ + + if (pParent->viewable && + ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && + REGION_NOTEMPTY(pScreen, &pParent->borderSize) && + RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, + &pParent->borderSize)) != rgnOUT) + { + if (!pParent->DIXsaveUnder) + { + pParent->DIXsaveUnder = TRUE; + (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); + } + } + else + { + if (pParent->DIXsaveUnder) + { + res = TRUE; + pParent->DIXsaveUnder = FALSE; + } + } + return res; +} + + +/*- + *----------------------------------------------------------------------- + * miChangeSaveUnder -- + * Change the save-under state of a tree of windows. Called when + * a window with saveUnder TRUE is mapped/unmapped/reconfigured. + * + * Results: + * TRUE if any windows need to have backing-store removed (which + * means that PostChangeSaveUnder needs to be called later to + * finish the job). + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +Bool +miChangeSaveUnder(pWin, first) + register WindowPtr pWin; + WindowPtr first; /* First window to check. + * Used when pWin was restacked */ +{ + RegionRec rgn; /* Area obscured by saveUnder windows */ + register ScreenPtr pScreen; + Bool res; + + if (!deltaSaveUndersViewable && !numSaveUndersViewable) + return FALSE; + numSaveUndersViewable += deltaSaveUndersViewable; + deltaSaveUndersViewable = 0; + pScreen = pWin->drawable.pScreen; + REGION_NULL(pScreen, &rgn); + res = miCheckSubSaveUnder (pWin->parent, + pWin->saveUnder ? first : pWin->nextSib, + &rgn); + REGION_UNINIT(pScreen, &rgn); + return res; +} + +/*- + *----------------------------------------------------------------------- + * miPostChangeSaveUnder -- + * Actually turn backing-store off for those windows that no longer + * need to have it on. + * + * Results: + * None. + * + * Side Effects: + * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those + * windows affected. + * + *----------------------------------------------------------------------- + */ +void +miPostChangeSaveUnder(pWin, pFirst) + WindowPtr pWin; + WindowPtr pFirst; +{ + register WindowPtr pParent, pChild; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + if (!(pParent = pWin->parent)) + return; + ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; + if (!pParent->DIXsaveUnder && + (pParent->backingStore == NotUseful) && pParent->backStorage) + (*ChangeWindowAttributes)(pParent, CWBackingStore); + if (!(pChild = pFirst)) + return; + while (1) + { + if (!pChild->DIXsaveUnder && + (pChild->backingStore == NotUseful) && pChild->backStorage) + (*ChangeWindowAttributes)(pChild, CWBackingStore); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib) + { + pChild = pChild->parent; + if (pChild == pParent) + return; + } + pChild = pChild->nextSib; + } +} + +void +miMarkWindow(pWin) + register WindowPtr pWin; +{ + register ValidatePtr val; + + if (pWin->valdata) + return; + val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); + val->before.oldAbsCorner.x = pWin->drawable.x; + val->before.oldAbsCorner.y = pWin->drawable.y; + val->before.borderVisible = NullRegion; + val->before.resized = FALSE; + pWin->valdata = val; +} + +Bool +miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) + WindowPtr pWin; + WindowPtr pFirst; + WindowPtr *ppLayerWin; +{ + register BoxPtr box; + register WindowPtr pChild, pLast; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + + /* 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 ( (pChild = pFirst) ) + { + box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); + pLast = pChild->parent->lastChild; + while (1) + { + if (pChild->viewable) + { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) + { + (* MarkWindow)(pChild); + anyMarked = TRUE; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + } + while (!pChild->nextSib && (pChild != pLast)) + pChild = pChild->parent; + if (pChild == pLast) + break; + pChild = pChild->nextSib; + } + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + return anyMarked; +} + +/***** + * miHandleValidateExposures(pWin) + * starting at pWin, draw background in any windows that have exposure + * regions, translate the regions, restore any backing store, + * and then send any regions still exposed to the client + *****/ +void +miHandleValidateExposures(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + register ValidatePtr val; + ScreenPtr pScreen; + WindowExposuresProcPtr WindowExposures; + + pScreen = pWin->drawable.pScreen; + + pChild = pWin; + WindowExposures = pChild->drawable.pScreen->WindowExposures; + while (1) + { + if ( (val = pChild->valdata) ) + { + if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) + (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, + &val->after.borderExposed, + PW_BORDER); + REGION_UNINIT(pScreen, &val->after.borderExposed); + (*WindowExposures)(pChild, &val->after.exposed, NullRegion); + REGION_UNINIT(pScreen, &val->after.exposed); + xfree(val); + pChild->valdata = (ValidatePtr)NULL; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +void +miMoveWindow(pWin, x, y, pNextSib, kind) + register WindowPtr pWin; + int x,y; + WindowPtr pNextSib; + VTKind kind; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + short bw; + RegionPtr oldRegion = NULL; + DDXPointRec oldpt; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr windowToValidate; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return ; + pScreen = pWin->drawable.pScreen; + bw = wBorderWidth (pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) + { + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->borderClip); + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + } + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + SetWinSize (pWin); + SetBorderSize (pWin); + + (*pScreen->PositionWindow)(pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) + { + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, windowToValidate, (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, pLayerWin, (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); + (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); + REGION_DESTROY(pScreen, oldRegion); + /* XXX need to retile border if ParentRelative origin */ + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + + +/* + * pValid is a region of the screen which has been + * successfully copied -- recomputed exposed regions for affected windows + */ + +static int +miRecomputeExposures ( + register WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + register ScreenPtr pScreen; + RegionPtr pValid = (RegionPtr)value; + + if (pWin->valdata) + { + pScreen = pWin->drawable.pScreen; + /* + * compute exposed regions of this window + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->clipList, pValid); + /* + * compute exposed regions of the border + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid); + return WT_WALKCHILDREN; + } + return WT_NOMATCH; +} + +void +miSlideAndSizeWindow(pWin, x, y, w, h, pSib) + register WindowPtr pWin; + int x,y; + unsigned int w, h; + WindowPtr pSib; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + unsigned short width = pWin->drawable.width, + height = pWin->drawable.height; + short oldx = pWin->drawable.x, + oldy = pWin->drawable.y; + int bw = wBorderWidth (pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion = NULL; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr pFirstChange; + register WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + register unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion = NULL; + RegionPtr destClip; /* portions of destination already written */ + RegionPtr oldWinClip = NULL; /* old clip list for window */ + RegionPtr borderVisible = NullRegion; /* visible area of the border */ + RegionPtr bsExposed = NullRegion; /* backing store exposures */ + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return ; + + pScreen = pWin->drawable.pScreen; + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) + { + anyMarked = FALSE; + /* + * save the visible region of the window + */ + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->winSize); + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = (RegionPtr) NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + g = pChild->winGravity; + if (g != UnmapGravity) + { + if (!gravitate[g]) + gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); + REGION_UNION(pScreen, gravitate[g], + gravitate[g], &pChild->borderClip); + } + else + { + UnmapWindow(pChild, TRUE); + anyMarked = TRUE; + } + } + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + + oldWinClip = NULL; + if (pWin->bitGravity != ForgetGravity) + { + oldWinClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldWinClip, &pWin->clipList); + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder (pWin)) + { + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) + { + if (shrunk || moved) + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, + &pWin->winSize); + else + REGION_COPY(pScreen, borderVisible, + &pWin->borderClip); + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize (pWin); + SetBorderSize (pWin); + + dw = (int)w - (int)width; + dh = (int)h - (int)height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow)(pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + pRegion = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->backStorage) + REGION_COPY(pScreen, pRegion, &pWin->clipList); + + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + + if (pWin->valdata) + { + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); + } + + GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pRegion = &pWin->clipList; /* a convenient empty region */ + if (pWin->bitGravity == ForgetGravity) + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, NullRegion, oldx, oldy); + else + { + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, nx - x, ny - y, pRegion, oldx, oldy); + } + } + + if (WasViewable) + { + /* avoid the border */ + if (HasBorder (pWin)) + { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) + { + REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip) + { + /* + * clip to new clipList + */ + REGION_COPY(pScreen, pRegion, oldWinClip); + REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); + REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) + { + if (gravitate[g]) + REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, + gravitate[g]); + } + REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else + { + REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); + REGION_DESTROY(pScreen, oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = NULL; + + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); + + /* clip to not overwrite already copied areas */ + + if (destClip) { + REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); + REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); + REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y +#ifdef COMPOSITE + || pWin->redirectDraw +#endif + ) + { + (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); + } + + /* remove any overwritten bits from the remaining useful bits */ + + REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->winGravity != g) + continue; + REGION_INTERSECT(pScreen, pRegion, + &pChild->borderClip, gravitate[g]); + TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (!destClip) + destClip = gravitate[g]; + else + { + REGION_UNION(pScreen, destClip, destClip, gravitate[g]); + REGION_DESTROY(pScreen, gravitate[g]); + } + } + + REGION_DESTROY(pScreen, oldRegion); + REGION_DESTROY(pScreen, pRegion); + if (destClip) + REGION_DESTROY(pScreen, destClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, + VTOther); + } + else if (bsExposed) + { + (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (pWin->realized) + WindowsRestructured (); +} + +WindowPtr +miGetLayerWindow(pWin) + WindowPtr pWin; +{ + return pWin->firstChild; +} + +#ifdef SHAPE +/****** + * + * miSetShape + * The border/window shape has changed. Recompute winSize/borderSize + * and send appropriate exposure events + */ + +void +miSetShape(pWin) + register WindowPtr pWin; +{ + Bool WasViewable = (Bool)(pWin->viewable); + register ScreenPtr pScreen = pWin->drawable.pScreen; + Bool anyMarked = FALSE; + RegionPtr pOldClip = NULL, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); +#ifdef NXAGENT_SERVER + + /* + * We got a few, rare, segfaults here after having + * started using the backing store. It may be a + * different bug but miChangeSaveUnder() calls mi- + * CheckSubSaveUnder() that, in turn, can change + * the backing store attribute of the window. This + * means that we may try to destroy the region + * even if it was not created at the beginning of + * this function as, at the time, the backing store + * was off. miCheckSubSaveUnder() appear to get a + * pointer to the parent, so maybe doesn't change + * the attribute of the window itself. This is to + * be better investigated. + */ + + if (WasViewable && pOldClip) + REGION_DESTROY(pScreen, pOldClip); +#else + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); +#endif + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + CheckCursorConfinement(pWin); +} +#endif + +/* Keeps the same inside(!) origin */ + +void +miChangeBorderWidth(pWin, width) + register WindowPtr pWin; + unsigned int width; +{ + int oldwidth; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + Bool WasViewable = (Bool)(pWin->viewable); + Bool HadBorder; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + oldwidth = wBorderWidth (pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + if (WasViewable && width < oldwidth) + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + + pWin->borderWidth = width; + SetBorderSize (pWin); + + if (WasViewable) + { + if (width > oldwidth) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + /* + * save the old border visible region to correctly compute + * borderExposed. + */ + if (pWin->valdata && HadBorder) + { + RegionPtr borderVisible; + borderVisible = REGION_CREATE(pScreen, NULL, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, + VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +miMarkUnrealizedWindow(pChild, pWin, fromConfigure) + WindowPtr pChild; + WindowPtr pWin; + Bool fromConfigure; +{ + if ((pChild != pWin) || fromConfigure) + { + REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); + REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); + } +} + +void +miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) +{ + ScreenPtr pScreen; + WindowPtr pChild; + + pScreen = pWin->drawable.pScreen; + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->drawable.depth == depth) + REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); + + if (pChild->firstChild) + miSegregateChildren(pChild, pReg, depth); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.X.original new file mode 100644 index 000000000..280d0f8eb --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.X.original @@ -0,0 +1,1184 @@ +/* $XFree86: xc/programs/Xserver/mi/miwindow.c,v 1.9tsi Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: miwindow.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "regionstr.h" +#include "region.h" +#include "mi.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" + +void +miClearToBackground(pWin, x, y, w, h, generateExposures) + WindowPtr pWin; + int x,y; + int w,h; + Bool generateExposures; +{ + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen; + BoxPtr extents; + int x1, y1, x2, y2; + + /* compute everything using ints to avoid overflow */ + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + extents = &pWin->clipList.extents; + + /* clip the resulting rectangle to the window clipList extents. This + * makes sure that the result will fit in a box, given that the + * screen is < 32768 on a side. + */ + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + { + x2 = x1 = 0; + y2 = y1 = 0; + } + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + pScreen = pWin->drawable.pScreen; + REGION_INIT(pScreen, ®, &box, 1); + if (pWin->backStorage) + { + /* + * If the window has backing-store on, call through the + * ClearToBackground vector to handle the special semantics + * (i.e. things backing store is to be cleared out and + * an Expose event is to be generated for those areas in backing + * store if generateExposures is TRUE). + */ + pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, + generateExposures); + } + + REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); + if (generateExposures) + (*pScreen->WindowExposures)(pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); + REGION_UNINIT(pScreen, ®); + if (pBSReg) + REGION_DESTROY(pScreen, pBSReg); +} + +/* + * For SaveUnders using backing-store. The idea is that when a window is mapped + * with saveUnder set TRUE, any windows it obscures will have its backing + * store turned on setting the DIXsaveUnder bit, + * The backing-store code must be written to allow for this + */ + +/*- + *----------------------------------------------------------------------- + * miCheckSubSaveUnder -- + * Check all the inferiors of a window for coverage by saveUnder + * windows. Called from ChangeSaveUnder and CheckSaveUnder. + * This code is very inefficient. + * + * Results: + * TRUE if any windows need to have backing-store removed. + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +static Bool +miCheckSubSaveUnder( + register WindowPtr pParent, /* Parent to check */ + WindowPtr pFirst, /* first reconfigured window */ + RegionPtr pRegion) /* Initial area obscured by saveUnder */ +{ + register WindowPtr pChild; /* Current child */ + register ScreenPtr pScreen; /* Screen to use */ + RegionRec SubRegion; /* Area of children obscured */ + Bool res = FALSE; /* result */ + Bool subInited=FALSE;/* SubRegion initialized */ + + pScreen = pParent->drawable.pScreen; + if ( (pChild = pParent->firstChild) ) + { + /* + * build region above first changed window + */ + + for (; pChild != pFirst; pChild = pChild->nextSib) + if (pChild->viewable && pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + + /* + * check region below and including first changed window + */ + + for (; pChild; pChild = pChild->nextSib) + { + if (pChild->viewable) + { + /* + * don't save under nephew/niece windows; + * use a separate region + */ + + if (pChild->firstChild) + { + if (!subInited) + { + REGION_NULL(pScreen, &SubRegion); + subInited = TRUE; + } + REGION_COPY(pScreen, &SubRegion, pRegion); + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + &SubRegion); + } + else + { + res |= miCheckSubSaveUnder(pChild, pChild->firstChild, + pRegion); + } + + if (pChild->saveUnder) + REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); + } + } + + if (subInited) + REGION_UNINIT(pScreen, &SubRegion); + } + + /* + * Check the state of this window. DIX save unders are + * enabled for viewable windows with some client expressing + * exposure interest and which intersect the save under region + */ + + if (pParent->viewable && + ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && + REGION_NOTEMPTY(pScreen, &pParent->borderSize) && + RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, + &pParent->borderSize)) != rgnOUT) + { + if (!pParent->DIXsaveUnder) + { + pParent->DIXsaveUnder = TRUE; + (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); + } + } + else + { + if (pParent->DIXsaveUnder) + { + res = TRUE; + pParent->DIXsaveUnder = FALSE; + } + } + return res; +} + + +/*- + *----------------------------------------------------------------------- + * miChangeSaveUnder -- + * Change the save-under state of a tree of windows. Called when + * a window with saveUnder TRUE is mapped/unmapped/reconfigured. + * + * Results: + * TRUE if any windows need to have backing-store removed (which + * means that PostChangeSaveUnder needs to be called later to + * finish the job). + * + * Side Effects: + * Windows may have backing-store turned on or off. + * + *----------------------------------------------------------------------- + */ +Bool +miChangeSaveUnder(pWin, first) + register WindowPtr pWin; + WindowPtr first; /* First window to check. + * Used when pWin was restacked */ +{ + RegionRec rgn; /* Area obscured by saveUnder windows */ + register ScreenPtr pScreen; + Bool res; + + if (!deltaSaveUndersViewable && !numSaveUndersViewable) + return FALSE; + numSaveUndersViewable += deltaSaveUndersViewable; + deltaSaveUndersViewable = 0; + pScreen = pWin->drawable.pScreen; + REGION_NULL(pScreen, &rgn); + res = miCheckSubSaveUnder (pWin->parent, + pWin->saveUnder ? first : pWin->nextSib, + &rgn); + REGION_UNINIT(pScreen, &rgn); + return res; +} + +/*- + *----------------------------------------------------------------------- + * miPostChangeSaveUnder -- + * Actually turn backing-store off for those windows that no longer + * need to have it on. + * + * Results: + * None. + * + * Side Effects: + * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those + * windows affected. + * + *----------------------------------------------------------------------- + */ +void +miPostChangeSaveUnder(pWin, pFirst) + WindowPtr pWin; + WindowPtr pFirst; +{ + register WindowPtr pParent, pChild; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + + if (!(pParent = pWin->parent)) + return; + ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; + if (!pParent->DIXsaveUnder && + (pParent->backingStore == NotUseful) && pParent->backStorage) + (*ChangeWindowAttributes)(pParent, CWBackingStore); + if (!(pChild = pFirst)) + return; + while (1) + { + if (!pChild->DIXsaveUnder && + (pChild->backingStore == NotUseful) && pChild->backStorage) + (*ChangeWindowAttributes)(pChild, CWBackingStore); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib) + { + pChild = pChild->parent; + if (pChild == pParent) + return; + } + pChild = pChild->nextSib; + } +} + +void +miMarkWindow(pWin) + register WindowPtr pWin; +{ + register ValidatePtr val; + + if (pWin->valdata) + return; + val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); + val->before.oldAbsCorner.x = pWin->drawable.x; + val->before.oldAbsCorner.y = pWin->drawable.y; + val->before.borderVisible = NullRegion; + val->before.resized = FALSE; + pWin->valdata = val; +} + +Bool +miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) + WindowPtr pWin; + WindowPtr pFirst; + WindowPtr *ppLayerWin; +{ + register BoxPtr box; + register WindowPtr pChild, pLast; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; + ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + + /* 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 ( (pChild = pFirst) ) + { + box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); + pLast = pChild->parent->lastChild; + while (1) + { + if (pChild->viewable) + { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) + { + (* MarkWindow)(pChild); + anyMarked = TRUE; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + } + while (!pChild->nextSib && (pChild != pLast)) + pChild = pChild->parent; + if (pChild == pLast) + break; + pChild = pChild->nextSib; + } + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + return anyMarked; +} + +/***** + * miHandleValidateExposures(pWin) + * starting at pWin, draw background in any windows that have exposure + * regions, translate the regions, restore any backing store, + * and then send any regions still exposed to the client + *****/ +void +miHandleValidateExposures(pWin) + WindowPtr pWin; +{ + register WindowPtr pChild; + register ValidatePtr val; + ScreenPtr pScreen; + WindowExposuresProcPtr WindowExposures; + + pScreen = pWin->drawable.pScreen; + + pChild = pWin; + WindowExposures = pChild->drawable.pScreen->WindowExposures; + while (1) + { + if ( (val = pChild->valdata) ) + { + if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) + (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, + &val->after.borderExposed, + PW_BORDER); + REGION_UNINIT(pScreen, &val->after.borderExposed); + (*WindowExposures)(pChild, &val->after.exposed, NullRegion); + REGION_UNINIT(pScreen, &val->after.exposed); + xfree(val); + pChild->valdata = (ValidatePtr)NULL; + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +void +miMoveWindow(pWin, x, y, pNextSib, kind) + register WindowPtr pWin; + int x,y; + WindowPtr pNextSib; + VTKind kind; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + short bw; + RegionPtr oldRegion = NULL; + DDXPointRec oldpt; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr windowToValidate; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be moved */ + if (!(pParent = pWin->parent)) + return ; + pScreen = pWin->drawable.pScreen; + bw = wBorderWidth (pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) + { + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->borderClip); + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + } + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + SetWinSize (pWin); + SetBorderSize (pWin); + + (*pScreen->PositionWindow)(pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) + { + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, windowToValidate, (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows) + (pWin, pLayerWin, (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); + (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); + REGION_DESTROY(pScreen, oldRegion); + /* XXX need to retile border if ParentRelative origin */ + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + + +/* + * pValid is a region of the screen which has been + * successfully copied -- recomputed exposed regions for affected windows + */ + +static int +miRecomputeExposures ( + register WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + register ScreenPtr pScreen; + RegionPtr pValid = (RegionPtr)value; + + if (pWin->valdata) + { + pScreen = pWin->drawable.pScreen; + /* + * compute exposed regions of this window + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->clipList, pValid); + /* + * compute exposed regions of the border + */ + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid); + return WT_WALKCHILDREN; + } + return WT_NOMATCH; +} + +void +miSlideAndSizeWindow(pWin, x, y, w, h, pSib) + register WindowPtr pWin; + int x,y; + unsigned int w, h; + WindowPtr pSib; +{ + WindowPtr pParent; + Bool WasViewable = (Bool)(pWin->viewable); + unsigned short width = pWin->drawable.width, + height = pWin->drawable.height; + short oldx = pWin->drawable.x, + oldy = pWin->drawable.y; + int bw = wBorderWidth (pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion = NULL; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + WindowPtr pFirstChange; + register WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + register unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion = NULL; + RegionPtr destClip; /* portions of destination already written */ + RegionPtr oldWinClip = NULL; /* old clip list for window */ + RegionPtr borderVisible = NullRegion; /* visible area of the border */ + RegionPtr bsExposed = NullRegion; /* backing store exposures */ + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return ; + + pScreen = pWin->drawable.pScreen; + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) + { + anyMarked = FALSE; + /* + * save the visible region of the window + */ + oldRegion = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldRegion, &pWin->winSize); + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = (RegionPtr) NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + g = pChild->winGravity; + if (g != UnmapGravity) + { + if (!gravitate[g]) + gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); + REGION_UNION(pScreen, gravitate[g], + gravitate[g], &pChild->borderClip); + } + else + { + UnmapWindow(pChild, TRUE); + anyMarked = TRUE; + } + } + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + + oldWinClip = NULL; + if (pWin->bitGravity != ForgetGravity) + { + oldWinClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, oldWinClip, &pWin->clipList); + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder (pWin)) + { + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) + { + if (shrunk || moved) + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, + &pWin->winSize); + else + REGION_COPY(pScreen, borderVisible, + &pWin->borderClip); + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize (pWin); + SetBorderSize (pWin); + + dw = (int)w - (int)width; + dh = (int)h - (int)height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow)(pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + pRegion = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->backStorage) + REGION_COPY(pScreen, pRegion, &pWin->clipList); + + if (pLayerWin == pWin) + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + (WindowPtr *)NULL); + else + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + + if (pWin->valdata) + { + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); + } + + GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pRegion = &pWin->clipList; /* a convenient empty region */ + if (pWin->bitGravity == ForgetGravity) + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, NullRegion, oldx, oldy); + else + { + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, nx - x, ny - y, pRegion, oldx, oldy); + } + } + + if (WasViewable) + { + /* avoid the border */ + if (HasBorder (pWin)) + { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) + { + REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip) + { + /* + * clip to new clipList + */ + REGION_COPY(pScreen, pRegion, oldWinClip); + REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); + REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) + { + if (gravitate[g]) + REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, + gravitate[g]); + } + REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else + { + REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); + REGION_DESTROY(pScreen, oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = NULL; + + for (g = 0; g <= StaticGravity; g++) + { + if (!gravitate[g]) + continue; + + GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); + + /* clip to not overwrite already copied areas */ + + if (destClip) { + REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); + REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); + REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y +#ifdef COMPOSITE + || pWin->redirectDraw +#endif + ) + { + (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); + } + + /* remove any overwritten bits from the remaining useful bits */ + + REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->winGravity != g) + continue; + REGION_INTERSECT(pScreen, pRegion, + &pChild->borderClip, gravitate[g]); + TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) + REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (!destClip) + destClip = gravitate[g]; + else + { + REGION_UNION(pScreen, destClip, destClip, gravitate[g]); + REGION_DESTROY(pScreen, gravitate[g]); + } + } + + REGION_DESTROY(pScreen, oldRegion); + REGION_DESTROY(pScreen, pRegion); + if (destClip) + REGION_DESTROY(pScreen, destClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, + VTOther); + } + else if (bsExposed) + { + (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); + REGION_DESTROY(pScreen, bsExposed); + } + if (pWin->realized) + WindowsRestructured (); +} + +WindowPtr +miGetLayerWindow(pWin) + WindowPtr pWin; +{ + return pWin->firstChild; +} + +#ifdef SHAPE +/****** + * + * miSetShape + * The border/window shape has changed. Recompute winSize/borderSize + * and send appropriate exposure events + */ + +void +miSetShape(pWin) + register WindowPtr pWin; +{ + Bool WasViewable = (Bool)(pWin->viewable); + register ScreenPtr pScreen = pWin->drawable.pScreen; + Bool anyMarked = FALSE; + RegionPtr pOldClip = NULL, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pLayerWin->parent); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + CheckCursorConfinement(pWin); +} +#endif + +/* Keeps the same inside(!) origin */ + +void +miChangeBorderWidth(pWin, width) + register WindowPtr pWin; + unsigned int width; +{ + int oldwidth; + Bool anyMarked = FALSE; + register ScreenPtr pScreen; + Bool WasViewable = (Bool)(pWin->viewable); + Bool HadBorder; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + oldwidth = wBorderWidth (pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + if (WasViewable && width < oldwidth) + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + + pWin->borderWidth = width; + SetBorderSize (pWin); + + if (WasViewable) + { + if (width > oldwidth) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); + /* + * save the old border visible region to correctly compute + * borderExposed. + */ + if (pWin->valdata && HadBorder) + { + RegionPtr borderVisible; + borderVisible = REGION_CREATE(pScreen, NULL, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, + VTOther); + } + if (pWin->realized) + WindowsRestructured (); +} + +void +miMarkUnrealizedWindow(pChild, pWin, fromConfigure) + WindowPtr pChild; + WindowPtr pWin; + Bool fromConfigure; +{ + if ((pChild != pWin) || fromConfigure) + { + REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); + REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); + } +} + +void +miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) +{ + ScreenPtr pScreen; + WindowPtr pChild; + + pScreen = pWin->drawable.pScreen; + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (pChild->drawable.depth == depth) + REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); + + if (pChild->firstChild) + miSegregateChildren(pChild, pReg, depth); + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c new file mode 100644 index 000000000..5d6f71475 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c @@ -0,0 +1,2220 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/picture.c,v 1.29 2002/11/23 02:38:15 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "NXpicturestr.h" + +#include "Screen.h" +#include "Pixmaps.h" +#include "Drawable.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +void *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual); + +void *nxagentMatchingFormats(PictFormatPtr pForm); + +int PictureScreenPrivateIndex = -1; +int PictureWindowPrivateIndex; +int PictureGeneration; +RESTYPE PictureType; +RESTYPE PictFormatType; +RESTYPE GlyphSetType; +int PictureCmapPolicy = PictureCmapPolicyDefault; + +typedef struct _formatInit { + CARD32 format; + CARD8 depth; +} FormatInitRec, *FormatInitPtr; + +void nxagentPictureCreateDefaultFormats(ScreenPtr pScreen, FormatInitRec *formats, int *nformats); + +/* Picture Private machinery */ + +static int picturePrivateCount; + +void +ResetPicturePrivateIndex (void) +{ + picturePrivateCount = 0; +} + +int +AllocatePicturePrivateIndex (void) +{ + return picturePrivateCount++; +} + +Bool +AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + unsigned int oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= ps->PicturePrivateLen) + { + unsigned int *nsizes; + + nsizes = (unsigned int *)xrealloc(ps->PicturePrivateSizes, + (index2 + 1) * sizeof(unsigned int)); + if (!nsizes) + return FALSE; + while (ps->PicturePrivateLen <= index2) + { + nsizes[ps->PicturePrivateLen++] = 0; + ps->totalPictureSize += sizeof(DevUnion); + } + ps->PicturePrivateSizes = nsizes; + } + oldamount = ps->PicturePrivateSizes[index2]; + if (amount > oldamount) + { + ps->PicturePrivateSizes[index2] = amount; + ps->totalPictureSize += (amount - oldamount); + } + + return TRUE; +} + + +Bool +PictureDestroyWindow (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + + while ((pPicture = GetPictureWindow(pWindow))) + { + SetPictureWindow(pWindow, pPicture->pNext); + if (pPicture->id) + FreeResource (pPicture->id, PictureType); + FreePicture ((pointer) pPicture, pPicture->id); + } + pScreen->DestroyWindow = ps->DestroyWindow; + ret = (*pScreen->DestroyWindow) (pWindow); + ps->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = PictureDestroyWindow; + return ret; +} + +Bool +PictureCloseScreen (int index, ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + int n; + + pScreen->CloseScreen = ps->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + PictureResetFilters (pScreen); + for (n = 0; n < ps->nformats; n++) + if (ps->formats[n].type == PictTypeIndexed) + (*ps->CloseIndexed) (pScreen, &ps->formats[n]); + SetPictureScreen(pScreen, 0); + if (ps->PicturePrivateSizes) + xfree (ps->PicturePrivateSizes); + xfree (ps->formats); + xfree (ps); + return ret; +} + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + pScreen->StoreColors = ps->StoreColors; + (*pScreen->StoreColors) (pColormap, ndef, pdef); + ps->StoreColors = pScreen->StoreColors; + pScreen->StoreColors = PictureStoreColors; + + if (pColormap->class == PseudoColor || pColormap->class == GrayScale) + { + PictFormatPtr format = ps->formats; + int nformats = ps->nformats; + + while (nformats--) + { + if (format->type == PictTypeIndexed && + format->index.pColormap == pColormap) + { + (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); + break; + } + format++; + } + } +} + +static int +visualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + int d, v; + DepthPtr pDepth; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + return 0; +} + +static int +addFormat (FormatInitRec formats[256], + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + formats[nformat].format = format; + formats[nformat].depth = depth; + + #ifdef DEBUG + fprintf(stderr, "addFormat: Added format [%lu] depth [%d].\n", format, depth); + #endif + + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) +{ + int nformats, f; + PictFormatPtr pFormats; + FormatInitRec formats[1024]; + CARD32 format; + +#ifndef NXAGENT_SERVER + + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int type; + int r, g, b; + int d; + DepthPtr pDepth; + +#endif + + nformats = 0; + +#ifdef NXAGENT_SERVER + + nxagentPictureCreateDefaultFormats(pScreen, formats, &nformats); + +#else + + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + formats[nformats].format = PICT_x8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + bpp = BitsPerPixel (depth); + + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + type = PICT_TYPE_OTHER; + /* + * Current rendering code supports only two direct formats, + * fields must be packed together at the bottom of the pixel + * and must be either RGB or BGR + */ + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + type = PICT_TYPE_ARGB; + } + else if (pVisual->offsetRed == 0 && + pVisual->offsetGreen == r && + pVisual->offsetBlue == r + g) + { + type = PICT_TYPE_ABGR; + } + if (type != PICT_TYPE_OTHER) + { + format = PICT_FORMAT(bpp, type, 0, r, g, b); + nformats = addFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); + nformats = addFormat (formats, nformats, format, depth); + break; + case StaticGray: + case GrayScale: + format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); + nformats = addFormat (formats, nformats, format, depth); + break; + } + } + + /* + * Walk supported depths and add useful Direct formats + */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + + switch (bpp) { + case 16: + /* depth 12 formats */ + if (pDepth->depth >= 12) + { + nformats = addFormat (formats, nformats, + PICT_x4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x4b4g4r4, pDepth->depth); + } + + /* depth 15 formats */ + if (pDepth->depth >= 15) + { + nformats = addFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x1b5g5r5, pDepth->depth); + } + /* depth 16 formats */ + if (pDepth->depth >= 16) + { + nformats = addFormat (formats, nformats, + PICT_a1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a1b5g5r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b5g6r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4b4g4r4, pDepth->depth); + } + break; + case 24: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b8g8r8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x8b8g8r8, pDepth->depth); + } + break; + } + } + +#endif + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_ARGB: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = (PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_B(format); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = 0; + break; + + case PICT_TYPE_ABGR: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = (PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_R(format); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = 0; + break; + + case PICT_TYPE_A: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + + /* remaining fields already set to zero */ + break; + + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + pFormats[f].type = PictTypeIndexed; + pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid; + break; + } + +#ifdef NXAGENT_SERVER + if (nxagentMatchingFormats(&pFormats[f]) != NULL) + { + #ifdef DEBUG + fprintf(stderr, "PictureCreateDefaultFormats: Format with type [%d] depth [%d] rgb [%d,%d,%d] " + "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d] matches.\n", + pFormats[f].type, pFormats[f].depth, pFormats[f].direct.red, pFormats[f].direct.green, + pFormats[f].direct.blue, pFormats[f].direct.redMask, pFormats[f].direct.greenMask, + pFormats[f].direct.blueMask, pFormats[f].direct.alpha, pFormats[f].direct.alphaMask); + #endif + } + else + { + #ifdef DEBUG + fprintf(stderr, "PictureCreateDefaultFormats: Format with type [%d] depth [%d] rgb [%d,%d,%d] " + "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d] doesn't match.\n", + pFormats[f].type, pFormats[f].depth, pFormats[f].direct.red, pFormats[f].direct.green, + pFormats[f].direct.blue, pFormats[f].direct.redMask, pFormats[f].direct.greenMask, + pFormats[f].direct.blueMask, pFormats[f].direct.alpha, pFormats[f].direct.alphaMask); + #endif + } +#endif + } + *nformatp = nformats; + return pFormats; +} + +static VisualPtr +PictureFindVisual (ScreenPtr pScreen, VisualID visual) +{ + int i; + VisualPtr pVisual; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid == visual) + return pVisual; + } + return 0; +} + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return FALSE; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->type == PictTypeIndexed && !format->index.pColormap) + { + if (format->index.vid == pScreen->rootVisual) + format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + else + { + VisualPtr pVisual; + + pVisual = PictureFindVisual (pScreen, format->index.vid); + if (CreateColormap (FakeClientID (0), pScreen, + pVisual, + &format->index.pColormap, AllocNone, + 0) != Success) + { + return FALSE; + } + } + if (!(*ps->InitIndexed) (pScreen, format)) + return FALSE; + } + format++; + } + return TRUE; +} + +Bool +PictureFinishInit (void) +{ + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + { + if (!PictureInitIndexedFormats (screenInfo.screens[s])) + return FALSE; + (void) AnimCurInit (screenInfo.screens[s]); + } + + return TRUE; +} + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return FALSE; + ps->subpixel = subpixel; + return TRUE; + +} + +int +PictureGetSubpixelOrder (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return SubPixelUnknown; + return ps->subpixel; +} + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + int type; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + switch (pVisual->class) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + type = PictTypeIndexed; + break; + case TrueColor: + case DirectColor: + type = PictTypeDirect; + break; + default: + return 0; + } + while (nformat--) + { + if (format->depth == depth && format->type == type) + { + if (type == PictTypeIndexed) + { + if (format->index.vid == pVisual->vid) + return format; + } + else + { + if (format->direct.redMask << format->direct.red == + pVisual->redMask && + format->direct.greenMask << format->direct.green == + pVisual->greenMask && + format->direct.blueMask << format->direct.blue == + pVisual->blueMask) + { + return format; + } + } + } + format++; + } + return 0; +} + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->depth == depth && format->format == (f & 0xffffff)) + return format; + format++; + } + return 0; +} + +int +PictureParseCmapPolicy (const char *name) +{ + if ( strcmp (name, "default" ) == 0) + return PictureCmapPolicyDefault; + else if ( strcmp (name, "mono" ) == 0) + return PictureCmapPolicyMono; + else if ( strcmp (name, "gray" ) == 0) + return PictureCmapPolicyGray; + else if ( strcmp (name, "color" ) == 0) + return PictureCmapPolicyColor; + else if ( strcmp (name, "all" ) == 0) + return PictureCmapPolicyAll; + else + return PictureCmapPolicyInvalid; +} + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + int n; + CARD32 type, a, r, g, b; + + if (PictureGeneration != serverGeneration) + { + PictureType = CreateNewResourceType (FreePicture); + if (!PictureType) + return FALSE; + PictFormatType = CreateNewResourceType (FreePictFormat); + if (!PictFormatType) + return FALSE; + GlyphSetType = CreateNewResourceType (FreeGlyphSet); + if (!GlyphSetType) + return FALSE; + PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (PictureScreenPrivateIndex < 0) + return FALSE; + PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); + PictureGeneration = serverGeneration; +#ifdef XResExtension + RegisterResourceName (PictureType, "PICTURE"); + RegisterResourceName (PictFormatType, "PICTFORMAT"); + RegisterResourceName (GlyphSetType, "GLYPHSET"); +#endif + } + if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) + return FALSE; + + if (!formats) + { + formats = PictureCreateDefaultFormats (pScreen, &nformats); + if (!formats) + return FALSE; + } + for (n = 0; n < nformats; n++) + { + if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) + { + xfree (formats); + return FALSE; + } + if (formats[n].type == PictTypeIndexed) + { + VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid); + if ((pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); + if (!ps) + { + xfree (formats); + return FALSE; + } + SetPictureScreen(pScreen, ps); + if (!GlyphInit (pScreen)) + { + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + ps->totalPictureSize = sizeof (PictureRec); + ps->PicturePrivateSizes = 0; + ps->PicturePrivateLen = 0; + + ps->formats = formats; + ps->fallback = formats; + ps->nformats = nformats; + + ps->filters = 0; + ps->nfilters = 0; + ps->filterAliases = 0; + ps->nfilterAliases = 0; + + ps->subpixel = SubPixelUnknown; + + ps->CloseScreen = pScreen->CloseScreen; + ps->DestroyWindow = pScreen->DestroyWindow; + ps->StoreColors = pScreen->StoreColors; + pScreen->DestroyWindow = PictureDestroyWindow; + pScreen->CloseScreen = PictureCloseScreen; + pScreen->StoreColors = PictureStoreColors; + + if (!PictureSetDefaultFilters (pScreen)) + { + PictureResetFilters (pScreen); + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + return TRUE; +} + +void +SetPictureToDefaults (PicturePtr pPicture) +{ + pPicture->refcnt = 1; + pPicture->repeat = 0; + pPicture->graphicsExposures = FALSE; + pPicture->subWindowMode = ClipByChildren; + pPicture->polyEdge = PolyEdgeSharp; + pPicture->polyMode = PolyModePrecise; + pPicture->freeCompClip = FALSE; + pPicture->clientClipType = CT_NONE; + pPicture->componentAlpha = FALSE; + pPicture->repeatType = RepeatNone; + + pPicture->alphaMap = 0; + pPicture->alphaOrigin.x = 0; + pPicture->alphaOrigin.y = 0; + + pPicture->clipOrigin.x = 0; + pPicture->clipOrigin.y = 0; + pPicture->clientClip = 0; + + pPicture->transform = 0; + + pPicture->dither = None; + pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); + pPicture->filter_params = 0; + pPicture->filter_nparams = 0; + + pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; + pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; + pPicture->pSourcePict = 0; +} + +PicturePtr +AllocatePicture (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture; + char *ptr; + DevUnion *ppriv; + unsigned int *sizes; + unsigned int size; + int i; + + pPicture = (PicturePtr) xalloc (ps->totalPictureSize); + if (!pPicture) + return 0; + ppriv = (DevUnion *)(pPicture + 1); + pPicture->devPrivates = ppriv; + sizes = ps->PicturePrivateSizes; + ptr = (char *)(ppriv + ps->PicturePrivateLen); + for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return pPicture; +} + +/* + * Let picture always point to the virtual pixmap. + * For sure this is not the best way to deal with + * the virtual frame-buffer. + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask vmask, + XID *vlist, + ClientPtr client, + int *error) +{ + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); + + pPicture = AllocatePicture (pDrawable->pScreen); + if (!pPicture) + { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pDrawable = pDrawable; + pPicture->pFormat = pFormat; + pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); + if (pDrawable->type == DRAWABLE_PIXMAP) + { + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + pPicture->pDrawable = nxagentVirtualDrawable(pDrawable); + + #endif + + ++((PixmapPtr)pDrawable)->refcnt; + pPicture->pNext = 0; + } + else + { + pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); + SetPictureWindow(((WindowPtr) pDrawable), pPicture); + } + + SetPictureToDefaults (pPicture); + + if (vmask) + *error = ChangePicture (pPicture, vmask, vlist, 0, client); + else + *error = Success; + if (*error == Success) + *error = (*ps->CreatePicture) (pPicture); + if (*error != Success) + { + FreePicture (pPicture, (XID) 0); + pPicture = 0; + } + return pPicture; +} + +static CARD32 xRenderColorToCard32(xRenderColor c) +{ + return + (c.alpha >> 8 << 24) | + (c.red >> 8 << 16) | + (c.green & 0xff00) | + (c.blue >> 8); +} + +static unsigned int premultiply(unsigned int x) +{ + unsigned int a = x >> 24; + unsigned int t = (x & 0xff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff) * a; + x = (x + ((x >> 8) & 0xff) + 0x80); + x &= 0xff00; + x |= t | (a << 24); + return x; +} + +static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a, + unsigned int y, unsigned int b) +{ + CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; + t >>= 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; + x &= 0xff00ff00; + x |= t; + return x; +} + +static void initGradientColorTable(SourcePictPtr pGradient, int *error) +{ + int begin_pos, end_pos; + xFixed incr, dpos; + int pos, current_stop; + PictGradientStopPtr stops = pGradient->linear.stops; + int nstops = pGradient->linear.nstops; + + /* The position where the gradient begins and ends */ + begin_pos = (stops[0].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16; + end_pos = (stops[nstops - 1].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16; + + pos = 0; /* The position in the color table. */ + + /* Up to first point */ + while (pos <= begin_pos) { + pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[0].color); + ++pos; + } + + incr = (1<<16)/ PICT_GRADIENT_STOPTABLE_SIZE; /* the double increment. */ + dpos = incr * pos; /* The position in terms of 0-1. */ + + current_stop = 0; /* We always interpolate between current and current + 1. */ + + /* Gradient area */ + while (pos < end_pos) { + unsigned int current_color = xRenderColorToCard32(stops[current_stop].color); + unsigned int next_color = xRenderColorToCard32(stops[current_stop + 1].color); + + int dist = (int)(256*(dpos - stops[current_stop].x) + / (stops[current_stop+1].x - stops[current_stop].x)); + int idist = 256 - dist; + + pGradient->linear.colorTable[pos] = premultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + + ++pos; + dpos += incr; + + if (dpos > stops[current_stop + 1].x) + ++current_stop; + } + + /* After last point */ + while (pos < PICT_GRADIENT_STOPTABLE_SIZE) { + pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[nstops - 1].color); + ++pos; + } +} + +static void initGradient(SourcePictPtr pGradient, int stopCount, + xFixed *stopPoints, xRenderColor *stopColors, int *error) +{ + int i; + xFixed dpos; + + if (stopCount <= 0) { + *error = BadValue; + return; + } + + dpos = -1; + for (i = 0; i < stopCount; ++i) { + if (stopPoints[i] <= dpos || stopPoints[i] > (1<<16)) { + *error = BadValue; + return; + } + dpos = stopPoints[i]; + } + + pGradient->linear.stops = xalloc(stopCount*sizeof(PictGradientStop)); + if (!pGradient->linear.stops) { + *error = BadAlloc; + return; + } + + pGradient->linear.nstops = stopCount; + + for (i = 0; i < stopCount; ++i) { + pGradient->linear.stops[i].x = stopPoints[i]; + pGradient->linear.stops[i].color = stopColors[i]; + } + initGradientColorTable(pGradient, error); +} + +static PicturePtr createSourcePicture(void) +{ + PicturePtr pPicture; + pPicture = (PicturePtr) xalloc(sizeof(PictureRec)); + pPicture->pDrawable = 0; + pPicture->pFormat = 0; + pPicture->pNext = 0; + + SetPictureToDefaults(pPicture); + return pPicture; +} + +PicturePtr +CreateSolidPicture (Picture pid, xRenderColor *color, int *error) +{ + PicturePtr pPicture; + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + pPicture->pSourcePict->type = SourcePictTypeSolidFill; + pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color); + return pPicture; +} + +PicturePtr +CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + if (p1->x == p2->x && p1->y == p2->y) { + *error = BadValue; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + + pPicture->pSourcePict->linear.type = SourcePictTypeLinear; + pPicture->pSourcePict->linear.p1 = *p1; + pPicture->pSourcePict->linear.p2 = *p2; + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +#define FixedToDouble(x) ((x)/65536.) + +PicturePtr +CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer, + xFixed innerRadius, xFixed outerRadius, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + PictRadialGradient *radial; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + { + double dx = (double)(inner->x - outer->x); + double dy = (double)(inner->y - outer->y); + if (sqrt(dx*dx + dy*dy) + (double)(innerRadius) > (double)(outerRadius)) { + *error = BadValue; + return 0; + } + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + radial = &pPicture->pSourcePict->radial; + + radial->type = SourcePictTypeRadial; + { + double x = (double)innerRadius / (double)outerRadius; + radial->dx = (outer->x - inner->x); + radial->dy = (outer->y - inner->y); + radial->fx = (inner->x) - x*radial->dx; + radial->fy = (inner->y) - x*radial->dy; + radial->m = 1./(1+x); + radial->b = -x*radial->m; + radial->dx /= 65536.; + radial->dy /= 65536.; + radial->fx /= 65536.; + radial->fy /= 65536.; + x = outerRadius/65536.; + radial->a = x*x - radial->dx*radial->dx - radial->dy*radial->dy; + } + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +PicturePtr +CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + + pPicture->pSourcePict->conical.type = SourcePictTypeConical; + pPicture->pSourcePict->conical.center = *center; + pPicture->pSourcePict->conical.angle = angle; + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) + +#define NEXT_PTR(_type) ((_type) ulist++->ptr) + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client) +{ + ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0; + PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0; + BITS32 index2; + int error = 0; + BITS32 maskQ; + + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + maskQ = vmask; + while (vmask && !error) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + pPicture->stateChanges |= index2; + switch (index2) + { + case CPRepeat: + { + unsigned int newr; + newr = NEXT_VAL(unsigned int); + if (newr <= RepeatReflect) + { + pPicture->repeat = (newr != RepeatNone); + pPicture->repeatType = newr; + } + else + { + client->errorValue = newr; + error = BadValue; + } + } + break; + case CPAlphaMap: + { + PicturePtr pAlpha; + + if (vlist) + { + Picture pid = NEXT_VAL(Picture); + + if (pid == None) + pAlpha = 0; + else + { + pAlpha = (PicturePtr) SecurityLookupIDByType(client, + pid, + PictureType, + SecurityWriteAccess|SecurityReadAccess); + if (!pAlpha) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + if (pAlpha->pDrawable->type != DRAWABLE_PIXMAP) + { + client->errorValue = pid; + error = BadMatch; + break; + } + } + } + else + pAlpha = NEXT_PTR(PicturePtr); + if (!error) + { + if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) + pAlpha->refcnt++; + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + pPicture->alphaMap = pAlpha; + } + } + break; + case CPAlphaXOrigin: + pPicture->alphaOrigin.x = NEXT_VAL(INT16); + break; + case CPAlphaYOrigin: + pPicture->alphaOrigin.y = NEXT_VAL(INT16); + break; + case CPClipXOrigin: + pPicture->clipOrigin.x = NEXT_VAL(INT16); + break; + case CPClipYOrigin: + pPicture->clipOrigin.y = NEXT_VAL(INT16); + break; + case CPClipMask: + { + Pixmap pid; + PixmapPtr pPixmap; + int clipType; + if (!pScreen) + return BadDrawable; + + if (vlist) + { + pid = NEXT_VAL(Pixmap); + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + { + clipType = CT_PIXMAP; + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + } + } + else + { + pPixmap = NEXT_PTR(PixmapPtr); + if (pPixmap) + clipType = CT_PIXMAP; + else + clipType = CT_NONE; + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + break; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + + #ifdef DEBUG + fprintf(stderr, "ChangePicture: Going to call ChangePictureClip with clipType [%d] pPixmap [%p].\n", + clipType, (void *) pPixmap); + #endif + + error = (*ps->ChangePictureClip)(pPicture, clipType, + (pointer)pPixmap, 0); + break; + } + case CPGraphicsExposure: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe <= xTrue) + pPicture->graphicsExposures = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPSubwindowMode: + { + unsigned int news; + news = NEXT_VAL(unsigned int); + if (news == ClipByChildren || news == IncludeInferiors) + pPicture->subWindowMode = news; + else + { + client->errorValue = news; + error = BadValue; + } + } + break; + case CPPolyEdge: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) + pPicture->polyEdge = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPPolyMode: + { + unsigned int newm; + newm = NEXT_VAL(unsigned int); + if (newm == PolyModePrecise || newm == PolyModeImprecise) + pPicture->polyMode = newm; + else + { + client->errorValue = newm; + error = BadValue; + } + } + break; + case CPDither: + pPicture->dither = NEXT_VAL(Atom); + break; + case CPComponentAlpha: + { + unsigned int newca; + + newca = NEXT_VAL (unsigned int); + if (newca <= xTrue) + pPicture->componentAlpha = newca; + else + { + client->errorValue = newca; + error = BadValue; + } + } + break; + default: + client->errorValue = maskQ; + error = BadValue; + break; + } + } + if (ps) + (*ps->ChangePicture) (pPicture, maskQ); + return error; +} + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + + clientClip = RECTS_TO_REGION(pScreen, + nRect, rects, CT_UNSORTED); + if (!clientClip) + return BadAlloc; + result =(*ps->ChangePictureClip) (pPicture, CT_REGION, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + +int +SetPictureClipRegion (PicturePtr pPicture, + int xOrigin, + int yOrigin, + RegionPtr pRegion) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + int type; + + if (pRegion) + { + type = CT_REGION; + clientClip = REGION_CREATE (pScreen, + REGION_EXTENTS(pScreen, pRegion), + REGION_NUM_RECTS(pRegion)); + if (!clientClip) + return BadAlloc; + if (!REGION_COPY (pSCreen, clientClip, pRegion)) + { + REGION_DESTROY (pScreen, clientClip); + return BadAlloc; + } + } + else + { + type = CT_NONE; + clientClip = 0; + } + + result =(*ps->ChangePictureClip) (pPicture, type, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + static const PictTransform identity = { { + { xFixed1, 0x00000, 0x00000 }, + { 0x00000, xFixed1, 0x00000 }, + { 0x00000, 0x00000, xFixed1 }, + } }; + + if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0) + transform = 0; + + if (transform) + { + if (!pPicture->transform) + { + pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); + if (!pPicture->transform) + return BadAlloc; + } + *pPicture->transform = *transform; + } + else + { + if (pPicture->transform) + { + xfree (pPicture->transform); + pPicture->transform = 0; + } + } + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + + return Success; +} + +void +CopyPicture (PicturePtr pSrc, + Mask mask, + PicturePtr pDst) +{ + PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen); + Mask origMask = mask; + + pDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pDst->stateChanges |= mask; + + while (mask) { + Mask bit = lowbit(mask); + + switch (bit) + { + case CPRepeat: + pDst->repeat = pSrc->repeat; + pDst->repeatType = pSrc->repeatType; + break; + case CPAlphaMap: + if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP) + pSrc->alphaMap->refcnt++; + if (pDst->alphaMap) + FreePicture ((pointer) pDst->alphaMap, (XID) 0); + pDst->alphaMap = pSrc->alphaMap; + break; + case CPAlphaXOrigin: + pDst->alphaOrigin.x = pSrc->alphaOrigin.x; + break; + case CPAlphaYOrigin: + pDst->alphaOrigin.y = pSrc->alphaOrigin.y; + break; + case CPClipXOrigin: + pDst->clipOrigin.x = pSrc->clipOrigin.x; + break; + case CPClipYOrigin: + pDst->clipOrigin.y = pSrc->clipOrigin.y; + break; + case CPClipMask: + switch (pSrc->clientClipType) { + case CT_NONE: + (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); + break; + case CT_REGION: + if (!pSrc->clientClip) { + (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); + } else { + RegionPtr clientClip; + RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip; + + clientClip = REGION_CREATE(pSrc->pDrawable->pScreen, + REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip), + REGION_NUM_RECTS(srcClientClip)); + (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0); + } + break; + default: + /* XXX: CT_PIXMAP unimplemented */ + break; + } + break; + case CPGraphicsExposure: + pDst->graphicsExposures = pSrc->graphicsExposures; + break; + case CPPolyEdge: + pDst->polyEdge = pSrc->polyEdge; + break; + case CPPolyMode: + pDst->polyMode = pSrc->polyMode; + break; + case CPDither: + pDst->dither = pSrc->dither; + break; + case CPComponentAlpha: + pDst->componentAlpha = pSrc->componentAlpha; + break; + } + mask &= ~bit; + } + + (*ps->ChangePicture)(pDst, origMask); +} + +static void +ValidateOnePicture (PicturePtr pPicture) +{ + if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber) + { + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); + pPicture->stateChanges = 0; + pPicture->serialNumber = pPicture->pDrawable->serialNumber; + } +} + +void +ValidatePicture(PicturePtr pPicture) +{ + ValidateOnePicture (pPicture); + if (pPicture->alphaMap) + ValidateOnePicture (pPicture->alphaMap); +} + +int +FreePicture (pointer value, + XID pid) +{ + PicturePtr pPicture = (PicturePtr) value; + + if (--pPicture->refcnt == 0) + { + if (pPicture->transform) + xfree (pPicture->transform); + if (!pPicture->pDrawable) { + if (pPicture->pSourcePict) { + if (pPicture->pSourcePict->type != SourcePictTypeSolidFill) + xfree(pPicture->pSourcePict->linear.stops); + xfree(pPicture->pSourcePict); + } + } else { + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + (*ps->DestroyPicture) (pPicture); + (*ps->DestroyPictureClip) (pPicture); + if (pPicture->pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PicturePtr *pPrev; + + for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); + *pPrev; + pPrev = &(*pPrev)->pNext) + { + if (*pPrev == pPicture) + { + *pPrev = pPicture->pNext; + break; + } + } + } + else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) + { + (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); + } + } + xfree (pPicture); + } + return Success; +} + +int +FreePictFormat (pointer pPictFormat, + XID pid) +{ + return Success; +} + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); +} + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + + #ifdef TEST + fprintf(stderr, "CompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); +} + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pDst); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); +} + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); +} + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); +} + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +AddTraps (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntrap, + xTrap *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + ValidatePicture (pPicture); + (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps); +} + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +Bool +PictureTransformPoint3d (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + *vector = result; + return TRUE; +} + + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + for (j = 0; j < 2; j++) + { + partial = (xFixed_48_16) result.vector[j] << 16; + v = partial / result.vector[2]; + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + vector->vector[j] = (xFixed) v; + } + vector->vector[2] = xFixed1; + return TRUE; +} + +#ifndef True +# define True 1 +#endif + +#ifndef False +# define False 0 +#endif + +void nxagentReconnectPictFormat(void*, XID, void*); + +Bool nxagentReconnectAllPictFormat(void *p) +{ + PictFormatPtr formats_old, formats; + int nformats, nformats_old; + VisualPtr pVisual; + Bool success = True; + Bool matched; + int i, n; + CARD32 type, a, r, g, b; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_PICTFORMAT_DEBUG) + fprintf(stderr, "nxagentReconnectAllPictFormat\n"); + #endif + + formats_old = GetPictureScreen(nxagentDefaultScreen) -> formats; + nformats_old = GetPictureScreen(nxagentDefaultScreen) -> nformats; + + /* + * TODO: We could copy PictureCreateDefaultFormats, + * in order not to waste ID with FakeClientID(). + */ + formats = PictureCreateDefaultFormats (nxagentDefaultScreen, &nformats); + + if (!formats) + return False; + + for (n = 0; n < nformats; n++) + { + if (formats[n].type == PictTypeIndexed) + { + pVisual = nxagentVisualFromID(nxagentDefaultScreen, formats[n].index.vid); + + if ((pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + + for (n = 0; n < nformats_old; n++) + { + for (i = 0, matched = False; (!matched) && (i < nformats); i++) + { + if (formats_old[n].format == formats[i].format && + formats_old[n].type == formats[i].type && + formats_old[n].direct.red == formats[i].direct.red && + formats_old[n].direct.green == formats[i].direct.green && + formats_old[n].direct.blue == formats[i].direct.blue && + formats_old[n].direct.redMask == formats[i].direct.redMask && + formats_old[n].direct.greenMask == formats[i].direct.greenMask && + formats_old[n].direct.blueMask == formats[i].direct.blueMask && + formats_old[n].direct.alpha == formats[i].direct.alpha && + formats_old[n].direct.alphaMask == formats[i].direct.alphaMask) + { + /* + * Regard depth 16 and 15 as were the same, if all other values match. + */ + + if ((formats_old[n].depth == formats[i].depth) || + ((formats_old[n].depth == 15 || formats_old[n].depth == 16) && + (formats[i].depth == 15 || formats[i].depth == 16))) + { + matched = True; + } + } + } + + if (!matched) + { + return False; + } + } + + xfree(formats); + + /* TODO: Perhaps do i have to do PictureFinishInit ?. */ + /* TODO: We have to check for new Render protocol version. */ + + for (i = 0; (i < MAXCLIENTS) && (success); i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], PictFormatType, nxagentReconnectPictFormat, &success); + } + } + + return success; +} + +/* + * It seem we don't have nothing + * to do for reconnect PictureFormat. + */ + +void nxagentReconnectPictFormat(void *p0, XID x1, void *p2) +{ + PictFormatPtr pFormat; + Bool *pBool; + + pFormat = (PictFormatPtr)p0; + pBool = (Bool*)p2; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_PICTFORMAT_DEBUG) + fprintf(stderr, "nxagentReconnectPictFormat.\n"); + #endif +} + +/* + * The set of picture formats may change considerably + * between different X servers. This poses a problem + * while migrating NX sessions, because a requisite to + * successfully reconnect the session is that all pic- + * ture formats have to be available on the new X server. + * To reduce such problems, we use a limited set of + * pictures available on the most X servers. + */ + +void nxagentPictureCreateDefaultFormats(ScreenPtr pScreen, FormatInitRec *formats, int *nformats) +{ + DepthPtr pDepth; + VisualPtr pVisual; + + CARD32 format; + CARD8 depth; + + int r, g, b; + int bpp; + int d; + int v; + + + formats[*nformats].format = PICT_a1; + formats[*nformats].depth = 1; + *nformats += 1; + formats[*nformats].format = PICT_a4; + formats[*nformats].depth = 4; + *nformats += 1; + formats[*nformats].format = PICT_a8; + formats[*nformats].depth = 8; + *nformats += 1; + formats[*nformats].format = PICT_a8r8g8b8; + formats[*nformats].depth = 32; + *nformats += 1; + + /* + * This format should be required by the + * protocol, but it's not used by Xgl. + * + * formats[*nformats].format = PICT_x8r8g8b8; + * formats[*nformats].depth = 32; + * *nformats += 1; + */ + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + + bpp = BitsPerPixel (depth); + + switch (pVisual->class) + { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + format = PICT_FORMAT(bpp, PICT_TYPE_ARGB, 0, r, g, b); + *nformats = addFormat (formats, *nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + case StaticGray: + case GrayScale: + break; + } + } + + for (d = 0; d < pScreen -> numDepths; d++) + { + pDepth = &pScreen -> allowedDepths[d]; + bpp = BitsPerPixel(pDepth -> depth); + + switch (bpp) { + case 16: + if (pDepth->depth == 15) + { + *nformats = addFormat (formats, *nformats, + PICT_x1r5g5b5, pDepth->depth); + } + + if (pDepth->depth == 16) + { + *nformats = addFormat (formats, *nformats, + PICT_r5g6b5, pDepth->depth); + } + break; + case 24: + if (pDepth->depth == 24) + { + *nformats = addFormat (formats, *nformats, + PICT_r8g8b8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth == 24) + { + *nformats = addFormat (formats, *nformats, + PICT_x8r8g8b8, pDepth->depth); + } + break; + } + } +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.NX.original new file mode 100644 index 000000000..5d6f71475 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.NX.original @@ -0,0 +1,2220 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/render/picture.c,v 1.29 2002/11/23 02:38:15 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "NXpicturestr.h" + +#include "Screen.h" +#include "Pixmaps.h" +#include "Drawable.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +void *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual); + +void *nxagentMatchingFormats(PictFormatPtr pForm); + +int PictureScreenPrivateIndex = -1; +int PictureWindowPrivateIndex; +int PictureGeneration; +RESTYPE PictureType; +RESTYPE PictFormatType; +RESTYPE GlyphSetType; +int PictureCmapPolicy = PictureCmapPolicyDefault; + +typedef struct _formatInit { + CARD32 format; + CARD8 depth; +} FormatInitRec, *FormatInitPtr; + +void nxagentPictureCreateDefaultFormats(ScreenPtr pScreen, FormatInitRec *formats, int *nformats); + +/* Picture Private machinery */ + +static int picturePrivateCount; + +void +ResetPicturePrivateIndex (void) +{ + picturePrivateCount = 0; +} + +int +AllocatePicturePrivateIndex (void) +{ + return picturePrivateCount++; +} + +Bool +AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + unsigned int oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= ps->PicturePrivateLen) + { + unsigned int *nsizes; + + nsizes = (unsigned int *)xrealloc(ps->PicturePrivateSizes, + (index2 + 1) * sizeof(unsigned int)); + if (!nsizes) + return FALSE; + while (ps->PicturePrivateLen <= index2) + { + nsizes[ps->PicturePrivateLen++] = 0; + ps->totalPictureSize += sizeof(DevUnion); + } + ps->PicturePrivateSizes = nsizes; + } + oldamount = ps->PicturePrivateSizes[index2]; + if (amount > oldamount) + { + ps->PicturePrivateSizes[index2] = amount; + ps->totalPictureSize += (amount - oldamount); + } + + return TRUE; +} + + +Bool +PictureDestroyWindow (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + + while ((pPicture = GetPictureWindow(pWindow))) + { + SetPictureWindow(pWindow, pPicture->pNext); + if (pPicture->id) + FreeResource (pPicture->id, PictureType); + FreePicture ((pointer) pPicture, pPicture->id); + } + pScreen->DestroyWindow = ps->DestroyWindow; + ret = (*pScreen->DestroyWindow) (pWindow); + ps->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = PictureDestroyWindow; + return ret; +} + +Bool +PictureCloseScreen (int index, ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + int n; + + pScreen->CloseScreen = ps->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + PictureResetFilters (pScreen); + for (n = 0; n < ps->nformats; n++) + if (ps->formats[n].type == PictTypeIndexed) + (*ps->CloseIndexed) (pScreen, &ps->formats[n]); + SetPictureScreen(pScreen, 0); + if (ps->PicturePrivateSizes) + xfree (ps->PicturePrivateSizes); + xfree (ps->formats); + xfree (ps); + return ret; +} + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + pScreen->StoreColors = ps->StoreColors; + (*pScreen->StoreColors) (pColormap, ndef, pdef); + ps->StoreColors = pScreen->StoreColors; + pScreen->StoreColors = PictureStoreColors; + + if (pColormap->class == PseudoColor || pColormap->class == GrayScale) + { + PictFormatPtr format = ps->formats; + int nformats = ps->nformats; + + while (nformats--) + { + if (format->type == PictTypeIndexed && + format->index.pColormap == pColormap) + { + (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); + break; + } + format++; + } + } +} + +static int +visualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + int d, v; + DepthPtr pDepth; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + return 0; +} + +static int +addFormat (FormatInitRec formats[256], + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + formats[nformat].format = format; + formats[nformat].depth = depth; + + #ifdef DEBUG + fprintf(stderr, "addFormat: Added format [%lu] depth [%d].\n", format, depth); + #endif + + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) +{ + int nformats, f; + PictFormatPtr pFormats; + FormatInitRec formats[1024]; + CARD32 format; + +#ifndef NXAGENT_SERVER + + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int type; + int r, g, b; + int d; + DepthPtr pDepth; + +#endif + + nformats = 0; + +#ifdef NXAGENT_SERVER + + nxagentPictureCreateDefaultFormats(pScreen, formats, &nformats); + +#else + + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + formats[nformats].format = PICT_x8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + bpp = BitsPerPixel (depth); + + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + type = PICT_TYPE_OTHER; + /* + * Current rendering code supports only two direct formats, + * fields must be packed together at the bottom of the pixel + * and must be either RGB or BGR + */ + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + type = PICT_TYPE_ARGB; + } + else if (pVisual->offsetRed == 0 && + pVisual->offsetGreen == r && + pVisual->offsetBlue == r + g) + { + type = PICT_TYPE_ABGR; + } + if (type != PICT_TYPE_OTHER) + { + format = PICT_FORMAT(bpp, type, 0, r, g, b); + nformats = addFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); + nformats = addFormat (formats, nformats, format, depth); + break; + case StaticGray: + case GrayScale: + format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); + nformats = addFormat (formats, nformats, format, depth); + break; + } + } + + /* + * Walk supported depths and add useful Direct formats + */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + + switch (bpp) { + case 16: + /* depth 12 formats */ + if (pDepth->depth >= 12) + { + nformats = addFormat (formats, nformats, + PICT_x4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x4b4g4r4, pDepth->depth); + } + + /* depth 15 formats */ + if (pDepth->depth >= 15) + { + nformats = addFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x1b5g5r5, pDepth->depth); + } + /* depth 16 formats */ + if (pDepth->depth >= 16) + { + nformats = addFormat (formats, nformats, + PICT_a1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a1b5g5r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b5g6r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4b4g4r4, pDepth->depth); + } + break; + case 24: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b8g8r8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x8b8g8r8, pDepth->depth); + } + break; + } + } + +#endif + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_ARGB: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = (PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_B(format); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = 0; + break; + + case PICT_TYPE_ABGR: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = (PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_R(format); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = 0; + break; + + case PICT_TYPE_A: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + + /* remaining fields already set to zero */ + break; + + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + pFormats[f].type = PictTypeIndexed; + pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid; + break; + } + +#ifdef NXAGENT_SERVER + if (nxagentMatchingFormats(&pFormats[f]) != NULL) + { + #ifdef DEBUG + fprintf(stderr, "PictureCreateDefaultFormats: Format with type [%d] depth [%d] rgb [%d,%d,%d] " + "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d] matches.\n", + pFormats[f].type, pFormats[f].depth, pFormats[f].direct.red, pFormats[f].direct.green, + pFormats[f].direct.blue, pFormats[f].direct.redMask, pFormats[f].direct.greenMask, + pFormats[f].direct.blueMask, pFormats[f].direct.alpha, pFormats[f].direct.alphaMask); + #endif + } + else + { + #ifdef DEBUG + fprintf(stderr, "PictureCreateDefaultFormats: Format with type [%d] depth [%d] rgb [%d,%d,%d] " + "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d] doesn't match.\n", + pFormats[f].type, pFormats[f].depth, pFormats[f].direct.red, pFormats[f].direct.green, + pFormats[f].direct.blue, pFormats[f].direct.redMask, pFormats[f].direct.greenMask, + pFormats[f].direct.blueMask, pFormats[f].direct.alpha, pFormats[f].direct.alphaMask); + #endif + } +#endif + } + *nformatp = nformats; + return pFormats; +} + +static VisualPtr +PictureFindVisual (ScreenPtr pScreen, VisualID visual) +{ + int i; + VisualPtr pVisual; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid == visual) + return pVisual; + } + return 0; +} + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return FALSE; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->type == PictTypeIndexed && !format->index.pColormap) + { + if (format->index.vid == pScreen->rootVisual) + format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + else + { + VisualPtr pVisual; + + pVisual = PictureFindVisual (pScreen, format->index.vid); + if (CreateColormap (FakeClientID (0), pScreen, + pVisual, + &format->index.pColormap, AllocNone, + 0) != Success) + { + return FALSE; + } + } + if (!(*ps->InitIndexed) (pScreen, format)) + return FALSE; + } + format++; + } + return TRUE; +} + +Bool +PictureFinishInit (void) +{ + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + { + if (!PictureInitIndexedFormats (screenInfo.screens[s])) + return FALSE; + (void) AnimCurInit (screenInfo.screens[s]); + } + + return TRUE; +} + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return FALSE; + ps->subpixel = subpixel; + return TRUE; + +} + +int +PictureGetSubpixelOrder (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return SubPixelUnknown; + return ps->subpixel; +} + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + int type; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + switch (pVisual->class) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + type = PictTypeIndexed; + break; + case TrueColor: + case DirectColor: + type = PictTypeDirect; + break; + default: + return 0; + } + while (nformat--) + { + if (format->depth == depth && format->type == type) + { + if (type == PictTypeIndexed) + { + if (format->index.vid == pVisual->vid) + return format; + } + else + { + if (format->direct.redMask << format->direct.red == + pVisual->redMask && + format->direct.greenMask << format->direct.green == + pVisual->greenMask && + format->direct.blueMask << format->direct.blue == + pVisual->blueMask) + { + return format; + } + } + } + format++; + } + return 0; +} + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->depth == depth && format->format == (f & 0xffffff)) + return format; + format++; + } + return 0; +} + +int +PictureParseCmapPolicy (const char *name) +{ + if ( strcmp (name, "default" ) == 0) + return PictureCmapPolicyDefault; + else if ( strcmp (name, "mono" ) == 0) + return PictureCmapPolicyMono; + else if ( strcmp (name, "gray" ) == 0) + return PictureCmapPolicyGray; + else if ( strcmp (name, "color" ) == 0) + return PictureCmapPolicyColor; + else if ( strcmp (name, "all" ) == 0) + return PictureCmapPolicyAll; + else + return PictureCmapPolicyInvalid; +} + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + int n; + CARD32 type, a, r, g, b; + + if (PictureGeneration != serverGeneration) + { + PictureType = CreateNewResourceType (FreePicture); + if (!PictureType) + return FALSE; + PictFormatType = CreateNewResourceType (FreePictFormat); + if (!PictFormatType) + return FALSE; + GlyphSetType = CreateNewResourceType (FreeGlyphSet); + if (!GlyphSetType) + return FALSE; + PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (PictureScreenPrivateIndex < 0) + return FALSE; + PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); + PictureGeneration = serverGeneration; +#ifdef XResExtension + RegisterResourceName (PictureType, "PICTURE"); + RegisterResourceName (PictFormatType, "PICTFORMAT"); + RegisterResourceName (GlyphSetType, "GLYPHSET"); +#endif + } + if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) + return FALSE; + + if (!formats) + { + formats = PictureCreateDefaultFormats (pScreen, &nformats); + if (!formats) + return FALSE; + } + for (n = 0; n < nformats; n++) + { + if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) + { + xfree (formats); + return FALSE; + } + if (formats[n].type == PictTypeIndexed) + { + VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid); + if ((pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); + if (!ps) + { + xfree (formats); + return FALSE; + } + SetPictureScreen(pScreen, ps); + if (!GlyphInit (pScreen)) + { + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + ps->totalPictureSize = sizeof (PictureRec); + ps->PicturePrivateSizes = 0; + ps->PicturePrivateLen = 0; + + ps->formats = formats; + ps->fallback = formats; + ps->nformats = nformats; + + ps->filters = 0; + ps->nfilters = 0; + ps->filterAliases = 0; + ps->nfilterAliases = 0; + + ps->subpixel = SubPixelUnknown; + + ps->CloseScreen = pScreen->CloseScreen; + ps->DestroyWindow = pScreen->DestroyWindow; + ps->StoreColors = pScreen->StoreColors; + pScreen->DestroyWindow = PictureDestroyWindow; + pScreen->CloseScreen = PictureCloseScreen; + pScreen->StoreColors = PictureStoreColors; + + if (!PictureSetDefaultFilters (pScreen)) + { + PictureResetFilters (pScreen); + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + return TRUE; +} + +void +SetPictureToDefaults (PicturePtr pPicture) +{ + pPicture->refcnt = 1; + pPicture->repeat = 0; + pPicture->graphicsExposures = FALSE; + pPicture->subWindowMode = ClipByChildren; + pPicture->polyEdge = PolyEdgeSharp; + pPicture->polyMode = PolyModePrecise; + pPicture->freeCompClip = FALSE; + pPicture->clientClipType = CT_NONE; + pPicture->componentAlpha = FALSE; + pPicture->repeatType = RepeatNone; + + pPicture->alphaMap = 0; + pPicture->alphaOrigin.x = 0; + pPicture->alphaOrigin.y = 0; + + pPicture->clipOrigin.x = 0; + pPicture->clipOrigin.y = 0; + pPicture->clientClip = 0; + + pPicture->transform = 0; + + pPicture->dither = None; + pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); + pPicture->filter_params = 0; + pPicture->filter_nparams = 0; + + pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; + pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; + pPicture->pSourcePict = 0; +} + +PicturePtr +AllocatePicture (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture; + char *ptr; + DevUnion *ppriv; + unsigned int *sizes; + unsigned int size; + int i; + + pPicture = (PicturePtr) xalloc (ps->totalPictureSize); + if (!pPicture) + return 0; + ppriv = (DevUnion *)(pPicture + 1); + pPicture->devPrivates = ppriv; + sizes = ps->PicturePrivateSizes; + ptr = (char *)(ppriv + ps->PicturePrivateLen); + for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return pPicture; +} + +/* + * Let picture always point to the virtual pixmap. + * For sure this is not the best way to deal with + * the virtual frame-buffer. + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask vmask, + XID *vlist, + ClientPtr client, + int *error) +{ + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); + + pPicture = AllocatePicture (pDrawable->pScreen); + if (!pPicture) + { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pDrawable = pDrawable; + pPicture->pFormat = pFormat; + pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); + if (pDrawable->type == DRAWABLE_PIXMAP) + { + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + pPicture->pDrawable = nxagentVirtualDrawable(pDrawable); + + #endif + + ++((PixmapPtr)pDrawable)->refcnt; + pPicture->pNext = 0; + } + else + { + pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); + SetPictureWindow(((WindowPtr) pDrawable), pPicture); + } + + SetPictureToDefaults (pPicture); + + if (vmask) + *error = ChangePicture (pPicture, vmask, vlist, 0, client); + else + *error = Success; + if (*error == Success) + *error = (*ps->CreatePicture) (pPicture); + if (*error != Success) + { + FreePicture (pPicture, (XID) 0); + pPicture = 0; + } + return pPicture; +} + +static CARD32 xRenderColorToCard32(xRenderColor c) +{ + return + (c.alpha >> 8 << 24) | + (c.red >> 8 << 16) | + (c.green & 0xff00) | + (c.blue >> 8); +} + +static unsigned int premultiply(unsigned int x) +{ + unsigned int a = x >> 24; + unsigned int t = (x & 0xff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff) * a; + x = (x + ((x >> 8) & 0xff) + 0x80); + x &= 0xff00; + x |= t | (a << 24); + return x; +} + +static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a, + unsigned int y, unsigned int b) +{ + CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; + t >>= 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; + x &= 0xff00ff00; + x |= t; + return x; +} + +static void initGradientColorTable(SourcePictPtr pGradient, int *error) +{ + int begin_pos, end_pos; + xFixed incr, dpos; + int pos, current_stop; + PictGradientStopPtr stops = pGradient->linear.stops; + int nstops = pGradient->linear.nstops; + + /* The position where the gradient begins and ends */ + begin_pos = (stops[0].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16; + end_pos = (stops[nstops - 1].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16; + + pos = 0; /* The position in the color table. */ + + /* Up to first point */ + while (pos <= begin_pos) { + pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[0].color); + ++pos; + } + + incr = (1<<16)/ PICT_GRADIENT_STOPTABLE_SIZE; /* the double increment. */ + dpos = incr * pos; /* The position in terms of 0-1. */ + + current_stop = 0; /* We always interpolate between current and current + 1. */ + + /* Gradient area */ + while (pos < end_pos) { + unsigned int current_color = xRenderColorToCard32(stops[current_stop].color); + unsigned int next_color = xRenderColorToCard32(stops[current_stop + 1].color); + + int dist = (int)(256*(dpos - stops[current_stop].x) + / (stops[current_stop+1].x - stops[current_stop].x)); + int idist = 256 - dist; + + pGradient->linear.colorTable[pos] = premultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + + ++pos; + dpos += incr; + + if (dpos > stops[current_stop + 1].x) + ++current_stop; + } + + /* After last point */ + while (pos < PICT_GRADIENT_STOPTABLE_SIZE) { + pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[nstops - 1].color); + ++pos; + } +} + +static void initGradient(SourcePictPtr pGradient, int stopCount, + xFixed *stopPoints, xRenderColor *stopColors, int *error) +{ + int i; + xFixed dpos; + + if (stopCount <= 0) { + *error = BadValue; + return; + } + + dpos = -1; + for (i = 0; i < stopCount; ++i) { + if (stopPoints[i] <= dpos || stopPoints[i] > (1<<16)) { + *error = BadValue; + return; + } + dpos = stopPoints[i]; + } + + pGradient->linear.stops = xalloc(stopCount*sizeof(PictGradientStop)); + if (!pGradient->linear.stops) { + *error = BadAlloc; + return; + } + + pGradient->linear.nstops = stopCount; + + for (i = 0; i < stopCount; ++i) { + pGradient->linear.stops[i].x = stopPoints[i]; + pGradient->linear.stops[i].color = stopColors[i]; + } + initGradientColorTable(pGradient, error); +} + +static PicturePtr createSourcePicture(void) +{ + PicturePtr pPicture; + pPicture = (PicturePtr) xalloc(sizeof(PictureRec)); + pPicture->pDrawable = 0; + pPicture->pFormat = 0; + pPicture->pNext = 0; + + SetPictureToDefaults(pPicture); + return pPicture; +} + +PicturePtr +CreateSolidPicture (Picture pid, xRenderColor *color, int *error) +{ + PicturePtr pPicture; + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + pPicture->pSourcePict->type = SourcePictTypeSolidFill; + pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color); + return pPicture; +} + +PicturePtr +CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + if (p1->x == p2->x && p1->y == p2->y) { + *error = BadValue; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + + pPicture->pSourcePict->linear.type = SourcePictTypeLinear; + pPicture->pSourcePict->linear.p1 = *p1; + pPicture->pSourcePict->linear.p2 = *p2; + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +#define FixedToDouble(x) ((x)/65536.) + +PicturePtr +CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer, + xFixed innerRadius, xFixed outerRadius, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + PictRadialGradient *radial; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + { + double dx = (double)(inner->x - outer->x); + double dy = (double)(inner->y - outer->y); + if (sqrt(dx*dx + dy*dy) + (double)(innerRadius) > (double)(outerRadius)) { + *error = BadValue; + return 0; + } + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + radial = &pPicture->pSourcePict->radial; + + radial->type = SourcePictTypeRadial; + { + double x = (double)innerRadius / (double)outerRadius; + radial->dx = (outer->x - inner->x); + radial->dy = (outer->y - inner->y); + radial->fx = (inner->x) - x*radial->dx; + radial->fy = (inner->y) - x*radial->dy; + radial->m = 1./(1+x); + radial->b = -x*radial->m; + radial->dx /= 65536.; + radial->dy /= 65536.; + radial->fx /= 65536.; + radial->fy /= 65536.; + x = outerRadius/65536.; + radial->a = x*x - radial->dx*radial->dx - radial->dy*radial->dy; + } + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +PicturePtr +CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + + pPicture->pSourcePict->conical.type = SourcePictTypeConical; + pPicture->pSourcePict->conical.center = *center; + pPicture->pSourcePict->conical.angle = angle; + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) + +#define NEXT_PTR(_type) ((_type) ulist++->ptr) + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client) +{ + ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0; + PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0; + BITS32 index2; + int error = 0; + BITS32 maskQ; + + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + maskQ = vmask; + while (vmask && !error) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + pPicture->stateChanges |= index2; + switch (index2) + { + case CPRepeat: + { + unsigned int newr; + newr = NEXT_VAL(unsigned int); + if (newr <= RepeatReflect) + { + pPicture->repeat = (newr != RepeatNone); + pPicture->repeatType = newr; + } + else + { + client->errorValue = newr; + error = BadValue; + } + } + break; + case CPAlphaMap: + { + PicturePtr pAlpha; + + if (vlist) + { + Picture pid = NEXT_VAL(Picture); + + if (pid == None) + pAlpha = 0; + else + { + pAlpha = (PicturePtr) SecurityLookupIDByType(client, + pid, + PictureType, + SecurityWriteAccess|SecurityReadAccess); + if (!pAlpha) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + if (pAlpha->pDrawable->type != DRAWABLE_PIXMAP) + { + client->errorValue = pid; + error = BadMatch; + break; + } + } + } + else + pAlpha = NEXT_PTR(PicturePtr); + if (!error) + { + if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) + pAlpha->refcnt++; + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + pPicture->alphaMap = pAlpha; + } + } + break; + case CPAlphaXOrigin: + pPicture->alphaOrigin.x = NEXT_VAL(INT16); + break; + case CPAlphaYOrigin: + pPicture->alphaOrigin.y = NEXT_VAL(INT16); + break; + case CPClipXOrigin: + pPicture->clipOrigin.x = NEXT_VAL(INT16); + break; + case CPClipYOrigin: + pPicture->clipOrigin.y = NEXT_VAL(INT16); + break; + case CPClipMask: + { + Pixmap pid; + PixmapPtr pPixmap; + int clipType; + if (!pScreen) + return BadDrawable; + + if (vlist) + { + pid = NEXT_VAL(Pixmap); + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + { + clipType = CT_PIXMAP; + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + } + } + else + { + pPixmap = NEXT_PTR(PixmapPtr); + if (pPixmap) + clipType = CT_PIXMAP; + else + clipType = CT_NONE; + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + break; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + + #ifdef DEBUG + fprintf(stderr, "ChangePicture: Going to call ChangePictureClip with clipType [%d] pPixmap [%p].\n", + clipType, (void *) pPixmap); + #endif + + error = (*ps->ChangePictureClip)(pPicture, clipType, + (pointer)pPixmap, 0); + break; + } + case CPGraphicsExposure: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe <= xTrue) + pPicture->graphicsExposures = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPSubwindowMode: + { + unsigned int news; + news = NEXT_VAL(unsigned int); + if (news == ClipByChildren || news == IncludeInferiors) + pPicture->subWindowMode = news; + else + { + client->errorValue = news; + error = BadValue; + } + } + break; + case CPPolyEdge: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) + pPicture->polyEdge = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPPolyMode: + { + unsigned int newm; + newm = NEXT_VAL(unsigned int); + if (newm == PolyModePrecise || newm == PolyModeImprecise) + pPicture->polyMode = newm; + else + { + client->errorValue = newm; + error = BadValue; + } + } + break; + case CPDither: + pPicture->dither = NEXT_VAL(Atom); + break; + case CPComponentAlpha: + { + unsigned int newca; + + newca = NEXT_VAL (unsigned int); + if (newca <= xTrue) + pPicture->componentAlpha = newca; + else + { + client->errorValue = newca; + error = BadValue; + } + } + break; + default: + client->errorValue = maskQ; + error = BadValue; + break; + } + } + if (ps) + (*ps->ChangePicture) (pPicture, maskQ); + return error; +} + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + + clientClip = RECTS_TO_REGION(pScreen, + nRect, rects, CT_UNSORTED); + if (!clientClip) + return BadAlloc; + result =(*ps->ChangePictureClip) (pPicture, CT_REGION, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + +int +SetPictureClipRegion (PicturePtr pPicture, + int xOrigin, + int yOrigin, + RegionPtr pRegion) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + int type; + + if (pRegion) + { + type = CT_REGION; + clientClip = REGION_CREATE (pScreen, + REGION_EXTENTS(pScreen, pRegion), + REGION_NUM_RECTS(pRegion)); + if (!clientClip) + return BadAlloc; + if (!REGION_COPY (pSCreen, clientClip, pRegion)) + { + REGION_DESTROY (pScreen, clientClip); + return BadAlloc; + } + } + else + { + type = CT_NONE; + clientClip = 0; + } + + result =(*ps->ChangePictureClip) (pPicture, type, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + static const PictTransform identity = { { + { xFixed1, 0x00000, 0x00000 }, + { 0x00000, xFixed1, 0x00000 }, + { 0x00000, 0x00000, xFixed1 }, + } }; + + if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0) + transform = 0; + + if (transform) + { + if (!pPicture->transform) + { + pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); + if (!pPicture->transform) + return BadAlloc; + } + *pPicture->transform = *transform; + } + else + { + if (pPicture->transform) + { + xfree (pPicture->transform); + pPicture->transform = 0; + } + } + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + + return Success; +} + +void +CopyPicture (PicturePtr pSrc, + Mask mask, + PicturePtr pDst) +{ + PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen); + Mask origMask = mask; + + pDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pDst->stateChanges |= mask; + + while (mask) { + Mask bit = lowbit(mask); + + switch (bit) + { + case CPRepeat: + pDst->repeat = pSrc->repeat; + pDst->repeatType = pSrc->repeatType; + break; + case CPAlphaMap: + if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP) + pSrc->alphaMap->refcnt++; + if (pDst->alphaMap) + FreePicture ((pointer) pDst->alphaMap, (XID) 0); + pDst->alphaMap = pSrc->alphaMap; + break; + case CPAlphaXOrigin: + pDst->alphaOrigin.x = pSrc->alphaOrigin.x; + break; + case CPAlphaYOrigin: + pDst->alphaOrigin.y = pSrc->alphaOrigin.y; + break; + case CPClipXOrigin: + pDst->clipOrigin.x = pSrc->clipOrigin.x; + break; + case CPClipYOrigin: + pDst->clipOrigin.y = pSrc->clipOrigin.y; + break; + case CPClipMask: + switch (pSrc->clientClipType) { + case CT_NONE: + (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); + break; + case CT_REGION: + if (!pSrc->clientClip) { + (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); + } else { + RegionPtr clientClip; + RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip; + + clientClip = REGION_CREATE(pSrc->pDrawable->pScreen, + REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip), + REGION_NUM_RECTS(srcClientClip)); + (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0); + } + break; + default: + /* XXX: CT_PIXMAP unimplemented */ + break; + } + break; + case CPGraphicsExposure: + pDst->graphicsExposures = pSrc->graphicsExposures; + break; + case CPPolyEdge: + pDst->polyEdge = pSrc->polyEdge; + break; + case CPPolyMode: + pDst->polyMode = pSrc->polyMode; + break; + case CPDither: + pDst->dither = pSrc->dither; + break; + case CPComponentAlpha: + pDst->componentAlpha = pSrc->componentAlpha; + break; + } + mask &= ~bit; + } + + (*ps->ChangePicture)(pDst, origMask); +} + +static void +ValidateOnePicture (PicturePtr pPicture) +{ + if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber) + { + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); + pPicture->stateChanges = 0; + pPicture->serialNumber = pPicture->pDrawable->serialNumber; + } +} + +void +ValidatePicture(PicturePtr pPicture) +{ + ValidateOnePicture (pPicture); + if (pPicture->alphaMap) + ValidateOnePicture (pPicture->alphaMap); +} + +int +FreePicture (pointer value, + XID pid) +{ + PicturePtr pPicture = (PicturePtr) value; + + if (--pPicture->refcnt == 0) + { + if (pPicture->transform) + xfree (pPicture->transform); + if (!pPicture->pDrawable) { + if (pPicture->pSourcePict) { + if (pPicture->pSourcePict->type != SourcePictTypeSolidFill) + xfree(pPicture->pSourcePict->linear.stops); + xfree(pPicture->pSourcePict); + } + } else { + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + (*ps->DestroyPicture) (pPicture); + (*ps->DestroyPictureClip) (pPicture); + if (pPicture->pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PicturePtr *pPrev; + + for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); + *pPrev; + pPrev = &(*pPrev)->pNext) + { + if (*pPrev == pPicture) + { + *pPrev = pPicture->pNext; + break; + } + } + } + else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) + { + (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); + } + } + xfree (pPicture); + } + return Success; +} + +int +FreePictFormat (pointer pPictFormat, + XID pid) +{ + return Success; +} + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); +} + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + + #ifdef TEST + fprintf(stderr, "CompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); +} + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pDst); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); +} + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); +} + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); +} + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +AddTraps (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntrap, + xTrap *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + ValidatePicture (pPicture); + (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps); +} + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +Bool +PictureTransformPoint3d (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + *vector = result; + return TRUE; +} + + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + for (j = 0; j < 2; j++) + { + partial = (xFixed_48_16) result.vector[j] << 16; + v = partial / result.vector[2]; + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + vector->vector[j] = (xFixed) v; + } + vector->vector[2] = xFixed1; + return TRUE; +} + +#ifndef True +# define True 1 +#endif + +#ifndef False +# define False 0 +#endif + +void nxagentReconnectPictFormat(void*, XID, void*); + +Bool nxagentReconnectAllPictFormat(void *p) +{ + PictFormatPtr formats_old, formats; + int nformats, nformats_old; + VisualPtr pVisual; + Bool success = True; + Bool matched; + int i, n; + CARD32 type, a, r, g, b; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_PICTFORMAT_DEBUG) + fprintf(stderr, "nxagentReconnectAllPictFormat\n"); + #endif + + formats_old = GetPictureScreen(nxagentDefaultScreen) -> formats; + nformats_old = GetPictureScreen(nxagentDefaultScreen) -> nformats; + + /* + * TODO: We could copy PictureCreateDefaultFormats, + * in order not to waste ID with FakeClientID(). + */ + formats = PictureCreateDefaultFormats (nxagentDefaultScreen, &nformats); + + if (!formats) + return False; + + for (n = 0; n < nformats; n++) + { + if (formats[n].type == PictTypeIndexed) + { + pVisual = nxagentVisualFromID(nxagentDefaultScreen, formats[n].index.vid); + + if ((pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + + for (n = 0; n < nformats_old; n++) + { + for (i = 0, matched = False; (!matched) && (i < nformats); i++) + { + if (formats_old[n].format == formats[i].format && + formats_old[n].type == formats[i].type && + formats_old[n].direct.red == formats[i].direct.red && + formats_old[n].direct.green == formats[i].direct.green && + formats_old[n].direct.blue == formats[i].direct.blue && + formats_old[n].direct.redMask == formats[i].direct.redMask && + formats_old[n].direct.greenMask == formats[i].direct.greenMask && + formats_old[n].direct.blueMask == formats[i].direct.blueMask && + formats_old[n].direct.alpha == formats[i].direct.alpha && + formats_old[n].direct.alphaMask == formats[i].direct.alphaMask) + { + /* + * Regard depth 16 and 15 as were the same, if all other values match. + */ + + if ((formats_old[n].depth == formats[i].depth) || + ((formats_old[n].depth == 15 || formats_old[n].depth == 16) && + (formats[i].depth == 15 || formats[i].depth == 16))) + { + matched = True; + } + } + } + + if (!matched) + { + return False; + } + } + + xfree(formats); + + /* TODO: Perhaps do i have to do PictureFinishInit ?. */ + /* TODO: We have to check for new Render protocol version. */ + + for (i = 0; (i < MAXCLIENTS) && (success); i++) + { + if (clients[i]) + { + FindClientResourcesByType(clients[i], PictFormatType, nxagentReconnectPictFormat, &success); + } + } + + return success; +} + +/* + * It seem we don't have nothing + * to do for reconnect PictureFormat. + */ + +void nxagentReconnectPictFormat(void *p0, XID x1, void *p2) +{ + PictFormatPtr pFormat; + Bool *pBool; + + pFormat = (PictFormatPtr)p0; + pBool = (Bool*)p2; + + #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_PICTFORMAT_DEBUG) + fprintf(stderr, "nxagentReconnectPictFormat.\n"); + #endif +} + +/* + * The set of picture formats may change considerably + * between different X servers. This poses a problem + * while migrating NX sessions, because a requisite to + * successfully reconnect the session is that all pic- + * ture formats have to be available on the new X server. + * To reduce such problems, we use a limited set of + * pictures available on the most X servers. + */ + +void nxagentPictureCreateDefaultFormats(ScreenPtr pScreen, FormatInitRec *formats, int *nformats) +{ + DepthPtr pDepth; + VisualPtr pVisual; + + CARD32 format; + CARD8 depth; + + int r, g, b; + int bpp; + int d; + int v; + + + formats[*nformats].format = PICT_a1; + formats[*nformats].depth = 1; + *nformats += 1; + formats[*nformats].format = PICT_a4; + formats[*nformats].depth = 4; + *nformats += 1; + formats[*nformats].format = PICT_a8; + formats[*nformats].depth = 8; + *nformats += 1; + formats[*nformats].format = PICT_a8r8g8b8; + formats[*nformats].depth = 32; + *nformats += 1; + + /* + * This format should be required by the + * protocol, but it's not used by Xgl. + * + * formats[*nformats].format = PICT_x8r8g8b8; + * formats[*nformats].depth = 32; + * *nformats += 1; + */ + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + + bpp = BitsPerPixel (depth); + + switch (pVisual->class) + { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + format = PICT_FORMAT(bpp, PICT_TYPE_ARGB, 0, r, g, b); + *nformats = addFormat (formats, *nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + case StaticGray: + case GrayScale: + break; + } + } + + for (d = 0; d < pScreen -> numDepths; d++) + { + pDepth = &pScreen -> allowedDepths[d]; + bpp = BitsPerPixel(pDepth -> depth); + + switch (bpp) { + case 16: + if (pDepth->depth == 15) + { + *nformats = addFormat (formats, *nformats, + PICT_x1r5g5b5, pDepth->depth); + } + + if (pDepth->depth == 16) + { + *nformats = addFormat (formats, *nformats, + PICT_r5g6b5, pDepth->depth); + } + break; + case 24: + if (pDepth->depth == 24) + { + *nformats = addFormat (formats, *nformats, + PICT_r8g8b8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth == 24) + { + *nformats = addFormat (formats, *nformats, + PICT_x8r8g8b8, pDepth->depth); + } + break; + } + } +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.X.original new file mode 100644 index 000000000..3ed60310e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.X.original @@ -0,0 +1,1864 @@ +/* + * $XFree86: xc/programs/Xserver/render/picture.c,v 1.29 2002/11/23 02:38:15 keithp Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" + +int PictureScreenPrivateIndex = -1; +int PictureWindowPrivateIndex; +int PictureGeneration; +RESTYPE PictureType; +RESTYPE PictFormatType; +RESTYPE GlyphSetType; +int PictureCmapPolicy = PictureCmapPolicyDefault; + +/* Picture Private machinery */ + +static int picturePrivateCount; + +void +ResetPicturePrivateIndex (void) +{ + picturePrivateCount = 0; +} + +int +AllocatePicturePrivateIndex (void) +{ + return picturePrivateCount++; +} + +Bool +AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + unsigned int oldamount; + + /* Round up sizes for proper alignment */ + amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); + + if (index2 >= ps->PicturePrivateLen) + { + unsigned int *nsizes; + + nsizes = (unsigned int *)xrealloc(ps->PicturePrivateSizes, + (index2 + 1) * sizeof(unsigned int)); + if (!nsizes) + return FALSE; + while (ps->PicturePrivateLen <= index2) + { + nsizes[ps->PicturePrivateLen++] = 0; + ps->totalPictureSize += sizeof(DevUnion); + } + ps->PicturePrivateSizes = nsizes; + } + oldamount = ps->PicturePrivateSizes[index2]; + if (amount > oldamount) + { + ps->PicturePrivateSizes[index2] = amount; + ps->totalPictureSize += (amount - oldamount); + } + + return TRUE; +} + + +Bool +PictureDestroyWindow (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + + while ((pPicture = GetPictureWindow(pWindow))) + { + SetPictureWindow(pWindow, pPicture->pNext); + if (pPicture->id) + FreeResource (pPicture->id, PictureType); + FreePicture ((pointer) pPicture, pPicture->id); + } + pScreen->DestroyWindow = ps->DestroyWindow; + ret = (*pScreen->DestroyWindow) (pWindow); + ps->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = PictureDestroyWindow; + return ret; +} + +Bool +PictureCloseScreen (int index, ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + Bool ret; + int n; + + pScreen->CloseScreen = ps->CloseScreen; + ret = (*pScreen->CloseScreen) (index, pScreen); + PictureResetFilters (pScreen); + for (n = 0; n < ps->nformats; n++) + if (ps->formats[n].type == PictTypeIndexed) + (*ps->CloseIndexed) (pScreen, &ps->formats[n]); + SetPictureScreen(pScreen, 0); + if (ps->PicturePrivateSizes) + xfree (ps->PicturePrivateSizes); + xfree (ps->formats); + xfree (ps); + return ret; +} + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + pScreen->StoreColors = ps->StoreColors; + (*pScreen->StoreColors) (pColormap, ndef, pdef); + ps->StoreColors = pScreen->StoreColors; + pScreen->StoreColors = PictureStoreColors; + + if (pColormap->class == PseudoColor || pColormap->class == GrayScale) + { + PictFormatPtr format = ps->formats; + int nformats = ps->nformats; + + while (nformats--) + { + if (format->type == PictTypeIndexed && + format->index.pColormap == pColormap) + { + (*ps->UpdateIndexed) (pScreen, format, ndef, pdef); + break; + } + format++; + } + } +} + +static int +visualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + int d, v; + DepthPtr pDepth; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + for (v = 0; v < pDepth->numVids; v++) + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + return 0; +} + +typedef struct _formatInit { + CARD32 format; + CARD8 depth; +} FormatInitRec, *FormatInitPtr; + +static int +addFormat (FormatInitRec formats[256], + int nformat, + CARD32 format, + CARD8 depth) +{ + int n; + + for (n = 0; n < nformat; n++) + if (formats[n].format == format && formats[n].depth == depth) + return nformat; + formats[nformat].format = format; + formats[nformat].depth = depth; + return ++nformat; +} + +#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1)) + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp) +{ + int nformats, f; + PictFormatPtr pFormats; + FormatInitRec formats[1024]; + CARD32 format; + CARD8 depth; + VisualPtr pVisual; + int v; + int bpp; + int type; + int r, g, b; + int d; + DepthPtr pDepth; + + nformats = 0; + /* formats required by protocol */ + formats[nformats].format = PICT_a1; + formats[nformats].depth = 1; + nformats++; + formats[nformats].format = PICT_a8; + formats[nformats].depth = 8; + nformats++; + formats[nformats].format = PICT_a4; + formats[nformats].depth = 4; + nformats++; + formats[nformats].format = PICT_a8r8g8b8; + formats[nformats].depth = 32; + nformats++; + formats[nformats].format = PICT_x8r8g8b8; + formats[nformats].depth = 32; + nformats++; + + /* now look through the depths and visuals adding other formats */ + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = &pScreen->visuals[v]; + depth = visualDepth (pScreen, pVisual); + if (!depth) + continue; + bpp = BitsPerPixel (depth); + switch (pVisual->class) { + case DirectColor: + case TrueColor: + r = Ones (pVisual->redMask); + g = Ones (pVisual->greenMask); + b = Ones (pVisual->blueMask); + type = PICT_TYPE_OTHER; + /* + * Current rendering code supports only two direct formats, + * fields must be packed together at the bottom of the pixel + * and must be either RGB or BGR + */ + if (pVisual->offsetBlue == 0 && + pVisual->offsetGreen == b && + pVisual->offsetRed == b + g) + { + type = PICT_TYPE_ARGB; + } + else if (pVisual->offsetRed == 0 && + pVisual->offsetGreen == r && + pVisual->offsetBlue == r + g) + { + type = PICT_TYPE_ABGR; + } + if (type != PICT_TYPE_OTHER) + { + format = PICT_FORMAT(bpp, type, 0, r, g, b); + nformats = addFormat (formats, nformats, format, depth); + } + break; + case StaticColor: + case PseudoColor: + format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v); + nformats = addFormat (formats, nformats, format, depth); + break; + case StaticGray: + case GrayScale: + format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v); + nformats = addFormat (formats, nformats, format, depth); + break; + } + } + /* + * Walk supported depths and add useful Direct formats + */ + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = &pScreen->allowedDepths[d]; + bpp = BitsPerPixel (pDepth->depth); + format = 0; + switch (bpp) { + case 16: + /* depth 12 formats */ + if (pDepth->depth >= 12) + { + nformats = addFormat (formats, nformats, + PICT_x4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x4b4g4r4, pDepth->depth); + } + /* depth 15 formats */ + if (pDepth->depth >= 15) + { + nformats = addFormat (formats, nformats, + PICT_x1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x1b5g5r5, pDepth->depth); + } + /* depth 16 formats */ + if (pDepth->depth >= 16) + { + nformats = addFormat (formats, nformats, + PICT_a1r5g5b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a1b5g5r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_r5g6b5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b5g6r5, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4r4g4b4, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_a4b4g4r4, pDepth->depth); + } + break; + case 24: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_b8g8r8, pDepth->depth); + } + break; + case 32: + if (pDepth->depth >= 24) + { + nformats = addFormat (formats, nformats, + PICT_x8r8g8b8, pDepth->depth); + nformats = addFormat (formats, nformats, + PICT_x8b8g8r8, pDepth->depth); + } + break; + } + } + + + pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); + if (!pFormats) + return 0; + memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); + for (f = 0; f < nformats; f++) + { + pFormats[f].id = FakeClientID (0); + pFormats[f].depth = formats[f].depth; + format = formats[f].format; + pFormats[f].format = format; + switch (PICT_FORMAT_TYPE(format)) { + case PICT_TYPE_ARGB: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_R(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = (PICT_FORMAT_G(format) + + PICT_FORMAT_B(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_B(format); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = 0; + break; + + case PICT_TYPE_ABGR: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + if (pFormats[f].direct.alphaMask) + pFormats[f].direct.alpha = (PICT_FORMAT_B(format) + + PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format)); + pFormats[f].direct.blue = (PICT_FORMAT_G(format) + + PICT_FORMAT_R(format)); + + pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format)); + pFormats[f].direct.green = PICT_FORMAT_R(format); + + pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format)); + pFormats[f].direct.red = 0; + break; + + case PICT_TYPE_A: + pFormats[f].type = PictTypeDirect; + + pFormats[f].direct.alpha = 0; + pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format)); + + /* remaining fields already set to zero */ + break; + + case PICT_TYPE_COLOR: + case PICT_TYPE_GRAY: + pFormats[f].type = PictTypeIndexed; + pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid; + break; + } + } + *nformatp = nformats; + return pFormats; +} + +static VisualPtr +PictureFindVisual (ScreenPtr pScreen, VisualID visual) +{ + int i; + VisualPtr pVisual; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid == visual) + return pVisual; + } + return 0; +} + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return FALSE; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->type == PictTypeIndexed && !format->index.pColormap) + { + if (format->index.vid == pScreen->rootVisual) + format->index.pColormap = (ColormapPtr) LookupIDByType(pScreen->defColormap, + RT_COLORMAP); + else + { + VisualPtr pVisual; + + pVisual = PictureFindVisual (pScreen, format->index.vid); + if (CreateColormap (FakeClientID (0), pScreen, + pVisual, + &format->index.pColormap, AllocNone, + 0) != Success) + { + return FALSE; + } + } + if (!(*ps->InitIndexed) (pScreen, format)) + return FALSE; + } + format++; + } + return TRUE; +} + +Bool +PictureFinishInit (void) +{ + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + { + if (!PictureInitIndexedFormats (screenInfo.screens[s])) + return FALSE; + (void) AnimCurInit (screenInfo.screens[s]); + } + + return TRUE; +} + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return FALSE; + ps->subpixel = subpixel; + return TRUE; + +} + +int +PictureGetSubpixelOrder (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!ps) + return SubPixelUnknown; + return ps->subpixel; +} + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + int type; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + switch (pVisual->class) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + type = PictTypeIndexed; + break; + case TrueColor: + case DirectColor: + type = PictTypeDirect; + break; + default: + return 0; + } + while (nformat--) + { + if (format->depth == depth && format->type == type) + { + if (type == PictTypeIndexed) + { + if (format->index.vid == pVisual->vid) + return format; + } + else + { + if (format->direct.redMask << format->direct.red == + pVisual->redMask && + format->direct.greenMask << format->direct.green == + pVisual->greenMask && + format->direct.blueMask << format->direct.blue == + pVisual->blueMask) + { + return format; + } + } + } + format++; + } + return 0; +} + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + PictFormatPtr format; + int nformat; + + if (!ps) + return 0; + format = ps->formats; + nformat = ps->nformats; + while (nformat--) + { + if (format->depth == depth && format->format == (f & 0xffffff)) + return format; + format++; + } + return 0; +} + +int +PictureParseCmapPolicy (const char *name) +{ + if ( strcmp (name, "default" ) == 0) + return PictureCmapPolicyDefault; + else if ( strcmp (name, "mono" ) == 0) + return PictureCmapPolicyMono; + else if ( strcmp (name, "gray" ) == 0) + return PictureCmapPolicyGray; + else if ( strcmp (name, "color" ) == 0) + return PictureCmapPolicyColor; + else if ( strcmp (name, "all" ) == 0) + return PictureCmapPolicyAll; + else + return PictureCmapPolicyInvalid; +} + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + int n; + CARD32 type, a, r, g, b; + + if (PictureGeneration != serverGeneration) + { + PictureType = CreateNewResourceType (FreePicture); + if (!PictureType) + return FALSE; + PictFormatType = CreateNewResourceType (FreePictFormat); + if (!PictFormatType) + return FALSE; + GlyphSetType = CreateNewResourceType (FreeGlyphSet); + if (!GlyphSetType) + return FALSE; + PictureScreenPrivateIndex = AllocateScreenPrivateIndex(); + if (PictureScreenPrivateIndex < 0) + return FALSE; + PictureWindowPrivateIndex = AllocateWindowPrivateIndex(); + PictureGeneration = serverGeneration; +#ifdef XResExtension + RegisterResourceName (PictureType, "PICTURE"); + RegisterResourceName (PictFormatType, "PICTFORMAT"); + RegisterResourceName (GlyphSetType, "GLYPHSET"); +#endif + } + if (!AllocateWindowPrivate (pScreen, PictureWindowPrivateIndex, 0)) + return FALSE; + + if (!formats) + { + formats = PictureCreateDefaultFormats (pScreen, &nformats); + if (!formats) + return FALSE; + } + for (n = 0; n < nformats; n++) + { + if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n))) + { + xfree (formats); + return FALSE; + } + if (formats[n].type == PictTypeIndexed) + { + VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid); + if ((pVisual->class | DynamicClass) == PseudoColor) + type = PICT_TYPE_COLOR; + else + type = PICT_TYPE_GRAY; + a = r = g = b = 0; + } + else + { + if ((formats[n].direct.redMask| + formats[n].direct.blueMask| + formats[n].direct.greenMask) == 0) + type = PICT_TYPE_A; + else if (formats[n].direct.red > formats[n].direct.blue) + type = PICT_TYPE_ARGB; + else + type = PICT_TYPE_ABGR; + a = Ones (formats[n].direct.alphaMask); + r = Ones (formats[n].direct.redMask); + g = Ones (formats[n].direct.greenMask); + b = Ones (formats[n].direct.blueMask); + } + formats[n].format = PICT_FORMAT(0,type,a,r,g,b); + } + ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec)); + if (!ps) + { + xfree (formats); + return FALSE; + } + SetPictureScreen(pScreen, ps); + if (!GlyphInit (pScreen)) + { + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + ps->totalPictureSize = sizeof (PictureRec); + ps->PicturePrivateSizes = 0; + ps->PicturePrivateLen = 0; + + ps->formats = formats; + ps->fallback = formats; + ps->nformats = nformats; + + ps->filters = 0; + ps->nfilters = 0; + ps->filterAliases = 0; + ps->nfilterAliases = 0; + + ps->subpixel = SubPixelUnknown; + + ps->CloseScreen = pScreen->CloseScreen; + ps->DestroyWindow = pScreen->DestroyWindow; + ps->StoreColors = pScreen->StoreColors; + pScreen->DestroyWindow = PictureDestroyWindow; + pScreen->CloseScreen = PictureCloseScreen; + pScreen->StoreColors = PictureStoreColors; + + if (!PictureSetDefaultFilters (pScreen)) + { + PictureResetFilters (pScreen); + SetPictureScreen(pScreen, 0); + xfree (formats); + xfree (ps); + return FALSE; + } + + return TRUE; +} + +void +SetPictureToDefaults (PicturePtr pPicture) +{ + pPicture->refcnt = 1; + pPicture->repeat = 0; + pPicture->graphicsExposures = FALSE; + pPicture->subWindowMode = ClipByChildren; + pPicture->polyEdge = PolyEdgeSharp; + pPicture->polyMode = PolyModePrecise; + pPicture->freeCompClip = FALSE; + pPicture->clientClipType = CT_NONE; + pPicture->componentAlpha = FALSE; + pPicture->repeatType = RepeatNone; + + pPicture->alphaMap = 0; + pPicture->alphaOrigin.x = 0; + pPicture->alphaOrigin.y = 0; + + pPicture->clipOrigin.x = 0; + pPicture->clipOrigin.y = 0; + pPicture->clientClip = 0; + + pPicture->transform = 0; + + pPicture->dither = None; + pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE); + pPicture->filter_params = 0; + pPicture->filter_nparams = 0; + + pPicture->serialNumber = GC_CHANGE_SERIAL_BIT; + pPicture->stateChanges = (1 << (CPLastBit+1)) - 1; + pPicture->pSourcePict = 0; +} + +PicturePtr +AllocatePicture (ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + PicturePtr pPicture; + char *ptr; + DevUnion *ppriv; + unsigned int *sizes; + unsigned int size; + int i; + + pPicture = (PicturePtr) xalloc (ps->totalPictureSize); + if (!pPicture) + return 0; + ppriv = (DevUnion *)(pPicture + 1); + pPicture->devPrivates = ppriv; + sizes = ps->PicturePrivateSizes; + ptr = (char *)(ppriv + ps->PicturePrivateLen); + for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + return pPicture; +} + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask vmask, + XID *vlist, + ClientPtr client, + int *error) +{ + PicturePtr pPicture; + PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); + + pPicture = AllocatePicture (pDrawable->pScreen); + if (!pPicture) + { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pDrawable = pDrawable; + pPicture->pFormat = pFormat; + pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24); + if (pDrawable->type == DRAWABLE_PIXMAP) + { + ++((PixmapPtr)pDrawable)->refcnt; + pPicture->pNext = 0; + } + else + { + pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable)); + SetPictureWindow(((WindowPtr) pDrawable), pPicture); + } + + SetPictureToDefaults (pPicture); + + if (vmask) + *error = ChangePicture (pPicture, vmask, vlist, 0, client); + else + *error = Success; + if (*error == Success) + *error = (*ps->CreatePicture) (pPicture); + if (*error != Success) + { + FreePicture (pPicture, (XID) 0); + pPicture = 0; + } + return pPicture; +} + +static CARD32 xRenderColorToCard32(xRenderColor c) +{ + return + (c.alpha >> 8 << 24) | + (c.red >> 8 << 16) | + (c.green & 0xff00) | + (c.blue >> 8); +} + +static unsigned int premultiply(unsigned int x) +{ + unsigned int a = x >> 24; + unsigned int t = (x & 0xff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff) * a; + x = (x + ((x >> 8) & 0xff) + 0x80); + x &= 0xff00; + x |= t | (a << 24); + return x; +} + +static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a, + unsigned int y, unsigned int b) +{ + CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; + t >>= 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; + x &= 0xff00ff00; + x |= t; + return x; +} + +static void initGradientColorTable(SourcePictPtr pGradient, int *error) +{ + int begin_pos, end_pos; + xFixed incr, dpos; + int pos, current_stop; + PictGradientStopPtr stops = pGradient->linear.stops; + int nstops = pGradient->linear.nstops; + + /* The position where the gradient begins and ends */ + begin_pos = (stops[0].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16; + end_pos = (stops[nstops - 1].x * PICT_GRADIENT_STOPTABLE_SIZE) >> 16; + + pos = 0; /* The position in the color table. */ + + /* Up to first point */ + while (pos <= begin_pos) { + pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[0].color); + ++pos; + } + + incr = (1<<16)/ PICT_GRADIENT_STOPTABLE_SIZE; /* the double increment. */ + dpos = incr * pos; /* The position in terms of 0-1. */ + + current_stop = 0; /* We always interpolate between current and current + 1. */ + + /* Gradient area */ + while (pos < end_pos) { + unsigned int current_color = xRenderColorToCard32(stops[current_stop].color); + unsigned int next_color = xRenderColorToCard32(stops[current_stop + 1].color); + + int dist = (int)(256*(dpos - stops[current_stop].x) + / (stops[current_stop+1].x - stops[current_stop].x)); + int idist = 256 - dist; + + pGradient->linear.colorTable[pos] = premultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + + ++pos; + dpos += incr; + + if (dpos > stops[current_stop + 1].x) + ++current_stop; + } + + /* After last point */ + while (pos < PICT_GRADIENT_STOPTABLE_SIZE) { + pGradient->linear.colorTable[pos] = xRenderColorToCard32(stops[nstops - 1].color); + ++pos; + } +} + +static void initGradient(SourcePictPtr pGradient, int stopCount, + xFixed *stopPoints, xRenderColor *stopColors, int *error) +{ + int i; + xFixed dpos; + + if (stopCount <= 0) { + *error = BadValue; + return; + } + + dpos = -1; + for (i = 0; i < stopCount; ++i) { + if (stopPoints[i] <= dpos || stopPoints[i] > (1<<16)) { + *error = BadValue; + return; + } + dpos = stopPoints[i]; + } + + pGradient->linear.stops = xalloc(stopCount*sizeof(PictGradientStop)); + if (!pGradient->linear.stops) { + *error = BadAlloc; + return; + } + + pGradient->linear.nstops = stopCount; + + for (i = 0; i < stopCount; ++i) { + pGradient->linear.stops[i].x = stopPoints[i]; + pGradient->linear.stops[i].color = stopColors[i]; + } + initGradientColorTable(pGradient, error); +} + +static PicturePtr createSourcePicture(void) +{ + PicturePtr pPicture; + pPicture = (PicturePtr) xalloc(sizeof(PictureRec)); + pPicture->pDrawable = 0; + pPicture->pFormat = 0; + pPicture->pNext = 0; + + SetPictureToDefaults(pPicture); + return pPicture; +} + +PicturePtr +CreateSolidPicture (Picture pid, xRenderColor *color, int *error) +{ + PicturePtr pPicture; + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + pPicture->pSourcePict->type = SourcePictTypeSolidFill; + pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color); + return pPicture; +} + +PicturePtr +CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + if (p1->x == p2->x && p1->y == p2->y) { + *error = BadValue; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + + pPicture->pSourcePict->linear.type = SourcePictTypeLinear; + pPicture->pSourcePict->linear.p1 = *p1; + pPicture->pSourcePict->linear.p2 = *p2; + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +#define FixedToDouble(x) ((x)/65536.) + +PicturePtr +CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer, + xFixed innerRadius, xFixed outerRadius, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + PictRadialGradient *radial; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + { + double dx = (double)(inner->x - outer->x); + double dy = (double)(inner->y - outer->y); + if (sqrt(dx*dx + dy*dy) + (double)(innerRadius) > (double)(outerRadius)) { + *error = BadValue; + return 0; + } + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + radial = &pPicture->pSourcePict->radial; + + radial->type = SourcePictTypeRadial; + { + double x = (double)innerRadius / (double)outerRadius; + radial->dx = (outer->x - inner->x); + radial->dy = (outer->y - inner->y); + radial->fx = (inner->x) - x*radial->dx; + radial->fy = (inner->y) - x*radial->dy; + radial->m = 1./(1+x); + radial->b = -x*radial->m; + radial->dx /= 65536.; + radial->dy /= 65536.; + radial->fx /= 65536.; + radial->fy /= 65536.; + x = outerRadius/65536.; + radial->a = x*x - radial->dx*radial->dx - radial->dy*radial->dy; + } + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +PicturePtr +CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle, + int nStops, xFixed *stops, xRenderColor *colors, int *error) +{ + PicturePtr pPicture; + + if (nStops < 2) { + *error = BadValue; + return 0; + } + + pPicture = createSourcePicture(); + if (!pPicture) { + *error = BadAlloc; + return 0; + } + + pPicture->id = pid; + pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient)); + if (!pPicture->pSourcePict) { + *error = BadAlloc; + xfree(pPicture); + return 0; + } + + pPicture->pSourcePict->conical.type = SourcePictTypeConical; + pPicture->pSourcePict->conical.center = *center; + pPicture->pSourcePict->conical.angle = angle; + + initGradient(pPicture->pSourcePict, nStops, stops, colors, error); + if (*error) { + xfree(pPicture); + return 0; + } + return pPicture; +} + +#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val) + +#define NEXT_PTR(_type) ((_type) ulist++->ptr) + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client) +{ + ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0; + PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0; + BITS32 index2; + int error = 0; + BITS32 maskQ; + + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + maskQ = vmask; + while (vmask && !error) + { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + pPicture->stateChanges |= index2; + switch (index2) + { + case CPRepeat: + { + unsigned int newr; + newr = NEXT_VAL(unsigned int); + if (newr <= RepeatReflect) + { + pPicture->repeat = (newr != RepeatNone); + pPicture->repeatType = newr; + } + else + { + client->errorValue = newr; + error = BadValue; + } + } + break; + case CPAlphaMap: + { + PicturePtr pAlpha; + + if (vlist) + { + Picture pid = NEXT_VAL(Picture); + + if (pid == None) + pAlpha = 0; + else + { + pAlpha = (PicturePtr) SecurityLookupIDByType(client, + pid, + PictureType, + SecurityWriteAccess|SecurityReadAccess); + if (!pAlpha) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + if (pAlpha->pDrawable->type != DRAWABLE_PIXMAP) + { + client->errorValue = pid; + error = BadMatch; + break; + } + } + } + else + pAlpha = NEXT_PTR(PicturePtr); + if (!error) + { + if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP) + pAlpha->refcnt++; + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + pPicture->alphaMap = pAlpha; + } + } + break; + case CPAlphaXOrigin: + pPicture->alphaOrigin.x = NEXT_VAL(INT16); + break; + case CPAlphaYOrigin: + pPicture->alphaOrigin.y = NEXT_VAL(INT16); + break; + case CPClipXOrigin: + pPicture->clipOrigin.x = NEXT_VAL(INT16); + break; + case CPClipYOrigin: + pPicture->clipOrigin.y = NEXT_VAL(INT16); + break; + case CPClipMask: + { + Pixmap pid; + PixmapPtr pPixmap; + int clipType; + if (!pScreen) + return BadDrawable; + + if (vlist) + { + pid = NEXT_VAL(Pixmap); + if (pid == None) + { + clipType = CT_NONE; + pPixmap = NullPixmap; + } + else + { + clipType = CT_PIXMAP; + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, + pid, + RT_PIXMAP, + SecurityReadAccess); + if (!pPixmap) + { + client->errorValue = pid; + error = BadPixmap; + break; + } + } + } + else + { + pPixmap = NEXT_PTR(PixmapPtr); + if (pPixmap) + clipType = CT_PIXMAP; + else + clipType = CT_NONE; + } + + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + break; + } + else + { + clipType = CT_PIXMAP; + pPixmap->refcnt++; + } + } + error = (*ps->ChangePictureClip)(pPicture, clipType, + (pointer)pPixmap, 0); + break; + } + case CPGraphicsExposure: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe <= xTrue) + pPicture->graphicsExposures = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPSubwindowMode: + { + unsigned int news; + news = NEXT_VAL(unsigned int); + if (news == ClipByChildren || news == IncludeInferiors) + pPicture->subWindowMode = news; + else + { + client->errorValue = news; + error = BadValue; + } + } + break; + case CPPolyEdge: + { + unsigned int newe; + newe = NEXT_VAL(unsigned int); + if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth) + pPicture->polyEdge = newe; + else + { + client->errorValue = newe; + error = BadValue; + } + } + break; + case CPPolyMode: + { + unsigned int newm; + newm = NEXT_VAL(unsigned int); + if (newm == PolyModePrecise || newm == PolyModeImprecise) + pPicture->polyMode = newm; + else + { + client->errorValue = newm; + error = BadValue; + } + } + break; + case CPDither: + pPicture->dither = NEXT_VAL(Atom); + break; + case CPComponentAlpha: + { + unsigned int newca; + + newca = NEXT_VAL (unsigned int); + if (newca <= xTrue) + pPicture->componentAlpha = newca; + else + { + client->errorValue = newca; + error = BadValue; + } + } + break; + default: + client->errorValue = maskQ; + error = BadValue; + break; + } + } + if (ps) + (*ps->ChangePicture) (pPicture, maskQ); + return error; +} + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + + clientClip = RECTS_TO_REGION(pScreen, + nRect, rects, CT_UNSORTED); + if (!clientClip) + return BadAlloc; + result =(*ps->ChangePictureClip) (pPicture, CT_REGION, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + +int +SetPictureClipRegion (PicturePtr pPicture, + int xOrigin, + int yOrigin, + RegionPtr pRegion) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + RegionPtr clientClip; + int result; + int type; + + if (pRegion) + { + type = CT_REGION; + clientClip = REGION_CREATE (pScreen, + REGION_EXTENTS(pScreen, pRegion), + REGION_NUM_RECTS(pRegion)); + if (!clientClip) + return BadAlloc; + if (!REGION_COPY (pSCreen, clientClip, pRegion)) + { + REGION_DESTROY (pScreen, clientClip); + return BadAlloc; + } + } + else + { + type = CT_NONE; + clientClip = 0; + } + + result =(*ps->ChangePictureClip) (pPicture, type, + (pointer) clientClip, 0); + if (result == Success) + { + pPicture->clipOrigin.x = xOrigin; + pPicture->clipOrigin.y = yOrigin; + pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask; + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + } + return result; +} + + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + static const PictTransform identity = { { + { xFixed1, 0x00000, 0x00000 }, + { 0x00000, xFixed1, 0x00000 }, + { 0x00000, 0x00000, xFixed1 }, + } }; + + if (transform && memcmp (transform, &identity, sizeof (PictTransform)) == 0) + transform = 0; + + if (transform) + { + if (!pPicture->transform) + { + pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform)); + if (!pPicture->transform) + return BadAlloc; + } + *pPicture->transform = *transform; + } + else + { + if (pPicture->transform) + { + xfree (pPicture->transform); + pPicture->transform = 0; + } + } + pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT; + + return Success; +} + +void +CopyPicture (PicturePtr pSrc, + Mask mask, + PicturePtr pDst) +{ + PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen); + Mask origMask = mask; + + pDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pDst->stateChanges |= mask; + + while (mask) { + Mask bit = lowbit(mask); + + switch (bit) + { + case CPRepeat: + pDst->repeat = pSrc->repeat; + pDst->repeatType = pSrc->repeatType; + break; + case CPAlphaMap: + if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP) + pSrc->alphaMap->refcnt++; + if (pDst->alphaMap) + FreePicture ((pointer) pDst->alphaMap, (XID) 0); + pDst->alphaMap = pSrc->alphaMap; + break; + case CPAlphaXOrigin: + pDst->alphaOrigin.x = pSrc->alphaOrigin.x; + break; + case CPAlphaYOrigin: + pDst->alphaOrigin.y = pSrc->alphaOrigin.y; + break; + case CPClipXOrigin: + pDst->clipOrigin.x = pSrc->clipOrigin.x; + break; + case CPClipYOrigin: + pDst->clipOrigin.y = pSrc->clipOrigin.y; + break; + case CPClipMask: + switch (pSrc->clientClipType) { + case CT_NONE: + (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); + break; + case CT_REGION: + if (!pSrc->clientClip) { + (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0); + } else { + RegionPtr clientClip; + RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip; + + clientClip = REGION_CREATE(pSrc->pDrawable->pScreen, + REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip), + REGION_NUM_RECTS(srcClientClip)); + (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0); + } + break; + default: + /* XXX: CT_PIXMAP unimplemented */ + break; + } + break; + case CPGraphicsExposure: + pDst->graphicsExposures = pSrc->graphicsExposures; + break; + case CPPolyEdge: + pDst->polyEdge = pSrc->polyEdge; + break; + case CPPolyMode: + pDst->polyMode = pSrc->polyMode; + break; + case CPDither: + pDst->dither = pSrc->dither; + break; + case CPComponentAlpha: + pDst->componentAlpha = pSrc->componentAlpha; + break; + } + mask &= ~bit; + } + + (*ps->ChangePicture)(pDst, origMask); +} + +static void +ValidateOnePicture (PicturePtr pPicture) +{ + if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber) + { + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + (*ps->ValidatePicture) (pPicture, pPicture->stateChanges); + pPicture->stateChanges = 0; + pPicture->serialNumber = pPicture->pDrawable->serialNumber; + } +} + +void +ValidatePicture(PicturePtr pPicture) +{ + ValidateOnePicture (pPicture); + if (pPicture->alphaMap) + ValidateOnePicture (pPicture->alphaMap); +} + +int +FreePicture (pointer value, + XID pid) +{ + PicturePtr pPicture = (PicturePtr) value; + + if (--pPicture->refcnt == 0) + { + if (pPicture->transform) + xfree (pPicture->transform); + if (!pPicture->pDrawable) { + if (pPicture->pSourcePict) { + if (pPicture->pSourcePict->type != SourcePictTypeSolidFill) + xfree(pPicture->pSourcePict->linear.stops); + xfree(pPicture->pSourcePict); + } + } else { + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + if (pPicture->alphaMap) + FreePicture ((pointer) pPicture->alphaMap, (XID) 0); + (*ps->DestroyPicture) (pPicture); + (*ps->DestroyPictureClip) (pPicture); + if (pPicture->pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PicturePtr *pPrev; + + for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr); + *pPrev; + pPrev = &(*pPrev)->pNext) + { + if (*pPrev == pPicture) + { + *pPrev = pPicture->pNext; + break; + } + } + } + else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) + { + (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable); + } + } + xfree (pPicture); + } + return Success; +} + +int +FreePictFormat (pointer pPictFormat, + XID pid) +{ + return Success; +} + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); +} + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); +} + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pDst); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); +} + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); +} + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles); +} + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture (pSrc); + ValidatePicture (pDst); + (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); +} + +void +AddTraps (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntrap, + xTrap *traps) +{ + PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen); + + ValidatePicture (pPicture); + (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps); +} + +#define MAX_FIXED_48_16 ((xFixed_48_16) 0x7fffffff) +#define MIN_FIXED_48_16 (-((xFixed_48_16) 1 << 31)) + +Bool +PictureTransformPoint3d (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + *vector = result; + return TRUE; +} + + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector) +{ + PictVector result; + int i, j; + xFixed_32_32 partial; + xFixed_48_16 v; + + for (j = 0; j < 3; j++) + { + v = 0; + for (i = 0; i < 3; i++) + { + partial = ((xFixed_48_16) transform->matrix[j][i] * + (xFixed_48_16) vector->vector[i]); + v += partial >> 16; + } + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + result.vector[j] = (xFixed) v; + } + if (!result.vector[2]) + return FALSE; + for (j = 0; j < 2; j++) + { + partial = (xFixed_48_16) result.vector[j] << 16; + v = partial / result.vector[2]; + if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16) + return FALSE; + vector->vector[j] = (xFixed) v; + } + vector->vector[2] = xFixed1; + return TRUE; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h new file mode 100644 index 000000000..255411a9b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h @@ -0,0 +1,678 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $Id: picturestr.h,v 1.15 2005/12/09 18:35:21 ajax Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original + * picturestr.h or symbols will be redefined. We + * should define a new types and cast when appro- + * priate. + */ + +#ifndef _PICTURESTR_H_ +#define _PICTURESTR_H_ + +#include "NXglyphstr.h" +#include "scrnintstr.h" +#include "resource.h" + +typedef struct _DirectFormat { + CARD16 red, redMask; + CARD16 green, greenMask; + CARD16 blue, blueMask; + CARD16 alpha, alphaMask; +} DirectFormatRec; + +typedef struct _IndexFormat { + VisualID vid; + ColormapPtr pColormap; + int nvalues; + xIndexValue *pValues; + void *devPrivate; +} IndexFormatRec; + +typedef struct _PictFormat { + CARD32 id; + CARD32 format; /* except bpp */ + unsigned char type; + unsigned char depth; + DirectFormatRec direct; + IndexFormatRec index; +} PictFormatRec; + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + +typedef struct _PictTransform { + xFixed matrix[3][3]; +} PictTransform, *PictTransformPtr; + +#define PICT_GRADIENT_STOPTABLE_SIZE 1024 +#define SourcePictTypeSolidFill 0 +#define SourcePictTypeLinear 1 +#define SourcePictTypeRadial 2 +#define SourcePictTypeConical 3 + +typedef struct _PictSolidFill { + unsigned int type; + CARD32 color; +} PictSolidFill, *PictSolidFillPtr; + +typedef struct _PictGradientStop { + xFixed x; + xRenderColor color; +} PictGradientStop, *PictGradientStopPtr; + +typedef struct _PictGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; +} PictGradient, *PictGradientPtr; + +typedef struct _PictLinearGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + xPointFixed p1; + xPointFixed p2; +} PictLinearGradient, *PictLinearGradientPtr; + +typedef struct _PictRadialGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + double fx; + double fy; + double dx; + double dy; + double a; + double m; + double b; +} PictRadialGradient, *PictRadialGradientPtr; + +typedef struct _PictConicalGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + xPointFixed center; + xFixed angle; +} PictConicalGradient, *PictConicalGradientPtr; + +typedef union _SourcePict { + unsigned int type; + PictSolidFill solidFill; + PictGradient gradient; + PictLinearGradient linear; + PictRadialGradient radial; + PictConicalGradient conical; +} SourcePict, *SourcePictPtr; + +typedef struct _Picture { + DrawablePtr pDrawable; + PictFormatPtr pFormat; + CARD32 format; /* PICT_FORMAT */ + int refcnt; + CARD32 id; + PicturePtr pNext; /* chain on same drawable */ + + unsigned int repeat : 1; + unsigned int graphicsExposures : 1; + unsigned int subWindowMode : 1; + unsigned int polyEdge : 1; + unsigned int polyMode : 1; + unsigned int freeCompClip : 1; + unsigned int clientClipType : 2; + unsigned int componentAlpha : 1; + unsigned int repeatType : 2; + unsigned int unused : 21; + + PicturePtr alphaMap; + DDXPointRec alphaOrigin; + + DDXPointRec clipOrigin; + pointer clientClip; + + Atom dither; + + unsigned long stateChanges; + unsigned long serialNumber; + + RegionPtr pCompositeClip; + + DevUnion *devPrivates; + + PictTransform *transform; + + int filter; + xFixed *filter_params; + int filter_nparams; + SourcePictPtr pSourcePict; +} PictureRec; + +typedef Bool (*PictFilterValidateParamsProcPtr) (PicturePtr pPicture, int id, + xFixed *params, int nparams); +typedef struct { + char *name; + int id; + PictFilterValidateParamsProcPtr ValidateParams; +} PictFilterRec, *PictFilterPtr; + +#define PictFilterNearest 0 +#define PictFilterBilinear 1 + +#define PictFilterFast 2 +#define PictFilterGood 3 +#define PictFilterBest 4 + +#define PictFilterConvolution 5 + +typedef struct { + char *alias; + int alias_id; + int filter_id; +} PictFilterAliasRec, *PictFilterAliasPtr; + +typedef int (*CreatePictureProcPtr) (PicturePtr pPicture); +typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture); +typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture, + int clipType, + pointer value, + int n); +typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture); + +typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture, + PictTransform *transform); + +typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture); + +typedef void (*ChangePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*CompositeProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef void (*GlyphsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs); + +typedef void (*CompositeRectsProcPtr) (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask, + xTrapezoid *trap, + int x_off, + int y_off); + +typedef void (*TrapezoidsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +typedef void (*TrianglesProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +typedef void (*AddTrapsProcPtr) (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntrap, + xTrap *traps); + +typedef void (*AddTrianglesProcPtr) (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntri, + xTriangle *tris); + +typedef struct _PictureScreen { + int totalPictureSize; + unsigned int *PicturePrivateSizes; + int PicturePrivateLen; + + PictFormatPtr formats; + PictFormatPtr fallback; + int nformats; + + CreatePictureProcPtr CreatePicture; + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + DestroyWindowProcPtr DestroyWindow; + CloseScreenProcPtr CloseScreen; + + StoreColorsProcPtr StoreColors; + + InitIndexedProcPtr InitIndexed; + CloseIndexedProcPtr CloseIndexed; + UpdateIndexedProcPtr UpdateIndexed; + + int subpixel; + + PictFilterPtr filters; + int nfilters; + PictFilterAliasPtr filterAliases; + int nfilterAliases; + + ChangePictureTransformProcPtr ChangePictureTransform; + ChangePictureFilterProcPtr ChangePictureFilter; + DestroyPictureFilterProcPtr DestroyPictureFilter; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; + + AddTrianglesProcPtr AddTriangles; + + AddTrapsProcPtr AddTraps; + +} PictureScreenRec, *PictureScreenPtr; + +extern int PictureScreenPrivateIndex; +extern int PictureWindowPrivateIndex; +extern RESTYPE PictureType; +extern RESTYPE PictFormatType; +extern RESTYPE GlyphSetType; + +#define GetPictureScreen(s) ((PictureScreenPtr) ((s)->devPrivates[PictureScreenPrivateIndex].ptr)) +#define GetPictureScreenIfSet(s) ((PictureScreenPrivateIndex != -1) ? GetPictureScreen(s) : NULL) +#define SetPictureScreen(s,p) ((s)->devPrivates[PictureScreenPrivateIndex].ptr = (pointer) (p)) +#define GetPictureWindow(w) ((PicturePtr) ((w)->devPrivates[PictureWindowPrivateIndex].ptr)) +#define SetPictureWindow(w,p) ((w)->devPrivates[PictureWindowPrivateIndex].ptr = (pointer) (p)) + +#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, PictureType, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +void +ResetPicturePrivateIndex (void); + +int +AllocatePicturePrivateIndex (void); + +Bool +AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount); + +Bool +PictureDestroyWindow (WindowPtr pWindow); + +Bool +PictureCloseScreen (int Index, ScreenPtr pScreen); + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef); + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen); + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel); + +int +PictureGetSubpixelOrder (ScreenPtr pScreen); + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp); + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual); + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format); + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +int +PictureGetFilterId (char *filter, int len, Bool makeit); + +char * +PictureGetFilterName (int id); + +int +PictureAddFilter (ScreenPtr pScreen, + char *filter, + PictFilterValidateParamsProcPtr ValidateParams); + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias); + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen); + +void +PictureResetFilters (ScreenPtr pScreen); + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len); + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams); + +Bool +PictureFinishInit (void); + +void +SetPictureToDefaults (PicturePtr pPicture); + +PicturePtr +AllocatePicture (ScreenPtr pScreen); + +#if 0 +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); +#endif + + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask mask, + XID *list, + ClientPtr client, + int *error); + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client); + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects); + +int +SetPictureClipRegion (PicturePtr pPicture, + int xOrigin, + int yOrigin, + RegionPtr pRegion); + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform); + +void +CopyPicture (PicturePtr pSrc, + Mask mask, + PicturePtr pDst); + +void +ValidatePicture(PicturePtr pPicture); + +int +FreePicture (pointer pPicture, + XID pid); + +int +FreePictFormat (pointer pPictFormat, + XID pid); + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs); + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles); + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector); + +Bool +PictureTransformPoint3d (PictTransformPtr transform, + PictVectorPtr vector); + +void RenderExtensionInit (void); + +Bool +AnimCurInit (ScreenPtr pScreen); + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor); + +void +AddTraps (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntraps, + xTrap *traps); + +PicturePtr +CreateSolidPicture (Picture pid, + xRenderColor *color, + int *error); + +PicturePtr +CreateLinearGradientPicture (Picture pid, + xPointFixed *p1, + xPointFixed *p2, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +PicturePtr +CreateRadialGradientPicture (Picture pid, + xPointFixed *inner, + xPointFixed *outer, + xFixed innerRadius, + xFixed outerRadius, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +PicturePtr +CreateConicalGradientPicture (Picture pid, + xPointFixed *center, + xFixed angle, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +#ifdef PANORAMIX +void PanoramiXRenderInit (void); +void PanoramiXRenderReset (void); +#endif + +#endif /* _PICTURESTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.NX.original new file mode 100644 index 000000000..255411a9b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.NX.original @@ -0,0 +1,678 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $Id: picturestr.h,v 1.15 2005/12/09 18:35:21 ajax Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/* + * This must keep the same symbol as the original + * picturestr.h or symbols will be redefined. We + * should define a new types and cast when appro- + * priate. + */ + +#ifndef _PICTURESTR_H_ +#define _PICTURESTR_H_ + +#include "NXglyphstr.h" +#include "scrnintstr.h" +#include "resource.h" + +typedef struct _DirectFormat { + CARD16 red, redMask; + CARD16 green, greenMask; + CARD16 blue, blueMask; + CARD16 alpha, alphaMask; +} DirectFormatRec; + +typedef struct _IndexFormat { + VisualID vid; + ColormapPtr pColormap; + int nvalues; + xIndexValue *pValues; + void *devPrivate; +} IndexFormatRec; + +typedef struct _PictFormat { + CARD32 id; + CARD32 format; /* except bpp */ + unsigned char type; + unsigned char depth; + DirectFormatRec direct; + IndexFormatRec index; +} PictFormatRec; + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + +typedef struct _PictTransform { + xFixed matrix[3][3]; +} PictTransform, *PictTransformPtr; + +#define PICT_GRADIENT_STOPTABLE_SIZE 1024 +#define SourcePictTypeSolidFill 0 +#define SourcePictTypeLinear 1 +#define SourcePictTypeRadial 2 +#define SourcePictTypeConical 3 + +typedef struct _PictSolidFill { + unsigned int type; + CARD32 color; +} PictSolidFill, *PictSolidFillPtr; + +typedef struct _PictGradientStop { + xFixed x; + xRenderColor color; +} PictGradientStop, *PictGradientStopPtr; + +typedef struct _PictGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; +} PictGradient, *PictGradientPtr; + +typedef struct _PictLinearGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + xPointFixed p1; + xPointFixed p2; +} PictLinearGradient, *PictLinearGradientPtr; + +typedef struct _PictRadialGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + double fx; + double fy; + double dx; + double dy; + double a; + double m; + double b; +} PictRadialGradient, *PictRadialGradientPtr; + +typedef struct _PictConicalGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + xPointFixed center; + xFixed angle; +} PictConicalGradient, *PictConicalGradientPtr; + +typedef union _SourcePict { + unsigned int type; + PictSolidFill solidFill; + PictGradient gradient; + PictLinearGradient linear; + PictRadialGradient radial; + PictConicalGradient conical; +} SourcePict, *SourcePictPtr; + +typedef struct _Picture { + DrawablePtr pDrawable; + PictFormatPtr pFormat; + CARD32 format; /* PICT_FORMAT */ + int refcnt; + CARD32 id; + PicturePtr pNext; /* chain on same drawable */ + + unsigned int repeat : 1; + unsigned int graphicsExposures : 1; + unsigned int subWindowMode : 1; + unsigned int polyEdge : 1; + unsigned int polyMode : 1; + unsigned int freeCompClip : 1; + unsigned int clientClipType : 2; + unsigned int componentAlpha : 1; + unsigned int repeatType : 2; + unsigned int unused : 21; + + PicturePtr alphaMap; + DDXPointRec alphaOrigin; + + DDXPointRec clipOrigin; + pointer clientClip; + + Atom dither; + + unsigned long stateChanges; + unsigned long serialNumber; + + RegionPtr pCompositeClip; + + DevUnion *devPrivates; + + PictTransform *transform; + + int filter; + xFixed *filter_params; + int filter_nparams; + SourcePictPtr pSourcePict; +} PictureRec; + +typedef Bool (*PictFilterValidateParamsProcPtr) (PicturePtr pPicture, int id, + xFixed *params, int nparams); +typedef struct { + char *name; + int id; + PictFilterValidateParamsProcPtr ValidateParams; +} PictFilterRec, *PictFilterPtr; + +#define PictFilterNearest 0 +#define PictFilterBilinear 1 + +#define PictFilterFast 2 +#define PictFilterGood 3 +#define PictFilterBest 4 + +#define PictFilterConvolution 5 + +typedef struct { + char *alias; + int alias_id; + int filter_id; +} PictFilterAliasRec, *PictFilterAliasPtr; + +typedef int (*CreatePictureProcPtr) (PicturePtr pPicture); +typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture); +typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture, + int clipType, + pointer value, + int n); +typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture); + +typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture, + PictTransform *transform); + +typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture); + +typedef void (*ChangePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*CompositeProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef void (*GlyphsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs); + +typedef void (*CompositeRectsProcPtr) (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask, + xTrapezoid *trap, + int x_off, + int y_off); + +typedef void (*TrapezoidsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +typedef void (*TrianglesProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +typedef void (*AddTrapsProcPtr) (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntrap, + xTrap *traps); + +typedef void (*AddTrianglesProcPtr) (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntri, + xTriangle *tris); + +typedef struct _PictureScreen { + int totalPictureSize; + unsigned int *PicturePrivateSizes; + int PicturePrivateLen; + + PictFormatPtr formats; + PictFormatPtr fallback; + int nformats; + + CreatePictureProcPtr CreatePicture; + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + DestroyWindowProcPtr DestroyWindow; + CloseScreenProcPtr CloseScreen; + + StoreColorsProcPtr StoreColors; + + InitIndexedProcPtr InitIndexed; + CloseIndexedProcPtr CloseIndexed; + UpdateIndexedProcPtr UpdateIndexed; + + int subpixel; + + PictFilterPtr filters; + int nfilters; + PictFilterAliasPtr filterAliases; + int nfilterAliases; + + ChangePictureTransformProcPtr ChangePictureTransform; + ChangePictureFilterProcPtr ChangePictureFilter; + DestroyPictureFilterProcPtr DestroyPictureFilter; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; + + AddTrianglesProcPtr AddTriangles; + + AddTrapsProcPtr AddTraps; + +} PictureScreenRec, *PictureScreenPtr; + +extern int PictureScreenPrivateIndex; +extern int PictureWindowPrivateIndex; +extern RESTYPE PictureType; +extern RESTYPE PictFormatType; +extern RESTYPE GlyphSetType; + +#define GetPictureScreen(s) ((PictureScreenPtr) ((s)->devPrivates[PictureScreenPrivateIndex].ptr)) +#define GetPictureScreenIfSet(s) ((PictureScreenPrivateIndex != -1) ? GetPictureScreen(s) : NULL) +#define SetPictureScreen(s,p) ((s)->devPrivates[PictureScreenPrivateIndex].ptr = (pointer) (p)) +#define GetPictureWindow(w) ((PicturePtr) ((w)->devPrivates[PictureWindowPrivateIndex].ptr)) +#define SetPictureWindow(w,p) ((w)->devPrivates[PictureWindowPrivateIndex].ptr = (pointer) (p)) + +#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, PictureType, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +void +ResetPicturePrivateIndex (void); + +int +AllocatePicturePrivateIndex (void); + +Bool +AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount); + +Bool +PictureDestroyWindow (WindowPtr pWindow); + +Bool +PictureCloseScreen (int Index, ScreenPtr pScreen); + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef); + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen); + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel); + +int +PictureGetSubpixelOrder (ScreenPtr pScreen); + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp); + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual); + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format); + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +int +PictureGetFilterId (char *filter, int len, Bool makeit); + +char * +PictureGetFilterName (int id); + +int +PictureAddFilter (ScreenPtr pScreen, + char *filter, + PictFilterValidateParamsProcPtr ValidateParams); + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias); + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen); + +void +PictureResetFilters (ScreenPtr pScreen); + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len); + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams); + +Bool +PictureFinishInit (void); + +void +SetPictureToDefaults (PicturePtr pPicture); + +PicturePtr +AllocatePicture (ScreenPtr pScreen); + +#if 0 +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); +#endif + + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask mask, + XID *list, + ClientPtr client, + int *error); + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client); + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects); + +int +SetPictureClipRegion (PicturePtr pPicture, + int xOrigin, + int yOrigin, + RegionPtr pRegion); + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform); + +void +CopyPicture (PicturePtr pSrc, + Mask mask, + PicturePtr pDst); + +void +ValidatePicture(PicturePtr pPicture); + +int +FreePicture (pointer pPicture, + XID pid); + +int +FreePictFormat (pointer pPictFormat, + XID pid); + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs); + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles); + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector); + +Bool +PictureTransformPoint3d (PictTransformPtr transform, + PictVectorPtr vector); + +void RenderExtensionInit (void); + +Bool +AnimCurInit (ScreenPtr pScreen); + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor); + +void +AddTraps (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntraps, + xTrap *traps); + +PicturePtr +CreateSolidPicture (Picture pid, + xRenderColor *color, + int *error); + +PicturePtr +CreateLinearGradientPicture (Picture pid, + xPointFixed *p1, + xPointFixed *p2, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +PicturePtr +CreateRadialGradientPicture (Picture pid, + xPointFixed *inner, + xPointFixed *outer, + xFixed innerRadius, + xFixed outerRadius, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +PicturePtr +CreateConicalGradientPicture (Picture pid, + xPointFixed *center, + xFixed angle, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +#ifdef PANORAMIX +void PanoramiXRenderInit (void); +void PanoramiXRenderReset (void); +#endif + +#endif /* _PICTURESTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.X.original new file mode 100644 index 000000000..4775793ab --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.X.original @@ -0,0 +1,654 @@ +/* + * $Id: picturestr.h,v 1.15 2005/12/09 18:35:21 ajax Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifndef _PICTURESTR_H_ +#define _PICTURESTR_H_ + +#include "glyphstr.h" +#include "scrnintstr.h" +#include "resource.h" + +typedef struct _DirectFormat { + CARD16 red, redMask; + CARD16 green, greenMask; + CARD16 blue, blueMask; + CARD16 alpha, alphaMask; +} DirectFormatRec; + +typedef struct _IndexFormat { + VisualID vid; + ColormapPtr pColormap; + int nvalues; + xIndexValue *pValues; + void *devPrivate; +} IndexFormatRec; + +typedef struct _PictFormat { + CARD32 id; + CARD32 format; /* except bpp */ + unsigned char type; + unsigned char depth; + DirectFormatRec direct; + IndexFormatRec index; +} PictFormatRec; + +typedef struct _PictVector { + xFixed vector[3]; +} PictVector, *PictVectorPtr; + +typedef struct _PictTransform { + xFixed matrix[3][3]; +} PictTransform, *PictTransformPtr; + +#define PICT_GRADIENT_STOPTABLE_SIZE 1024 +#define SourcePictTypeSolidFill 0 +#define SourcePictTypeLinear 1 +#define SourcePictTypeRadial 2 +#define SourcePictTypeConical 3 + +typedef struct _PictSolidFill { + unsigned int type; + CARD32 color; +} PictSolidFill, *PictSolidFillPtr; + +typedef struct _PictGradientStop { + xFixed x; + xRenderColor color; +} PictGradientStop, *PictGradientStopPtr; + +typedef struct _PictGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; +} PictGradient, *PictGradientPtr; + +typedef struct _PictLinearGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + xPointFixed p1; + xPointFixed p2; +} PictLinearGradient, *PictLinearGradientPtr; + +typedef struct _PictRadialGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + double fx; + double fy; + double dx; + double dy; + double a; + double m; + double b; +} PictRadialGradient, *PictRadialGradientPtr; + +typedef struct _PictConicalGradient { + unsigned int type; + int nstops; + PictGradientStopPtr stops; + CARD32 colorTable[PICT_GRADIENT_STOPTABLE_SIZE]; + xPointFixed center; + xFixed angle; +} PictConicalGradient, *PictConicalGradientPtr; + +typedef union _SourcePict { + unsigned int type; + PictSolidFill solidFill; + PictGradient gradient; + PictLinearGradient linear; + PictRadialGradient radial; + PictConicalGradient conical; +} SourcePict, *SourcePictPtr; + +typedef struct _Picture { + DrawablePtr pDrawable; + PictFormatPtr pFormat; + CARD32 format; /* PICT_FORMAT */ + int refcnt; + CARD32 id; + PicturePtr pNext; /* chain on same drawable */ + + unsigned int repeat : 1; + unsigned int graphicsExposures : 1; + unsigned int subWindowMode : 1; + unsigned int polyEdge : 1; + unsigned int polyMode : 1; + unsigned int freeCompClip : 1; + unsigned int clientClipType : 2; + unsigned int componentAlpha : 1; + unsigned int repeatType : 2; + unsigned int unused : 21; + + PicturePtr alphaMap; + DDXPointRec alphaOrigin; + + DDXPointRec clipOrigin; + pointer clientClip; + + Atom dither; + + unsigned long stateChanges; + unsigned long serialNumber; + + RegionPtr pCompositeClip; + + DevUnion *devPrivates; + + PictTransform *transform; + + int filter; + xFixed *filter_params; + int filter_nparams; + SourcePictPtr pSourcePict; +} PictureRec; + +typedef Bool (*PictFilterValidateParamsProcPtr) (PicturePtr pPicture, int id, + xFixed *params, int nparams); +typedef struct { + char *name; + int id; + PictFilterValidateParamsProcPtr ValidateParams; +} PictFilterRec, *PictFilterPtr; + +#define PictFilterNearest 0 +#define PictFilterBilinear 1 + +#define PictFilterFast 2 +#define PictFilterGood 3 +#define PictFilterBest 4 + +#define PictFilterConvolution 5 + +typedef struct { + char *alias; + int alias_id; + int filter_id; +} PictFilterAliasRec, *PictFilterAliasPtr; + +typedef int (*CreatePictureProcPtr) (PicturePtr pPicture); +typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture); +typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture, + int clipType, + pointer value, + int n); +typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture); + +typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture, + PictTransform *transform); + +typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture); + +typedef void (*ChangePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture, + Mask mask); +typedef void (*CompositeProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef void (*GlyphsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs); + +typedef void (*CompositeRectsProcPtr) (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask, + xTrapezoid *trap, + int x_off, + int y_off); + +typedef void (*TrapezoidsProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +typedef void (*TrianglesProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris); + +typedef void (*TriStripProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef void (*TriFanProcPtr) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points); + +typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat); + +typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +typedef void (*AddTrapsProcPtr) (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntrap, + xTrap *traps); + +typedef void (*AddTrianglesProcPtr) (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntri, + xTriangle *tris); + +typedef struct _PictureScreen { + int totalPictureSize; + unsigned int *PicturePrivateSizes; + int PicturePrivateLen; + + PictFormatPtr formats; + PictFormatPtr fallback; + int nformats; + + CreatePictureProcPtr CreatePicture; + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + DestroyWindowProcPtr DestroyWindow; + CloseScreenProcPtr CloseScreen; + + StoreColorsProcPtr StoreColors; + + InitIndexedProcPtr InitIndexed; + CloseIndexedProcPtr CloseIndexed; + UpdateIndexedProcPtr UpdateIndexed; + + int subpixel; + + PictFilterPtr filters; + int nfilters; + PictFilterAliasPtr filterAliases; + int nfilterAliases; + + ChangePictureTransformProcPtr ChangePictureTransform; + ChangePictureFilterProcPtr ChangePictureFilter; + DestroyPictureFilterProcPtr DestroyPictureFilter; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; + + AddTrianglesProcPtr AddTriangles; + + AddTrapsProcPtr AddTraps; + +} PictureScreenRec, *PictureScreenPtr; + +extern int PictureScreenPrivateIndex; +extern int PictureWindowPrivateIndex; +extern RESTYPE PictureType; +extern RESTYPE PictFormatType; +extern RESTYPE GlyphSetType; + +#define GetPictureScreen(s) ((PictureScreenPtr) ((s)->devPrivates[PictureScreenPrivateIndex].ptr)) +#define GetPictureScreenIfSet(s) ((PictureScreenPrivateIndex != -1) ? GetPictureScreen(s) : NULL) +#define SetPictureScreen(s,p) ((s)->devPrivates[PictureScreenPrivateIndex].ptr = (pointer) (p)) +#define GetPictureWindow(w) ((PicturePtr) ((w)->devPrivates[PictureWindowPrivateIndex].ptr)) +#define SetPictureWindow(w,p) ((w)->devPrivates[PictureWindowPrivateIndex].ptr = (pointer) (p)) + +#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, PictureType, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +void +ResetPicturePrivateIndex (void); + +int +AllocatePicturePrivateIndex (void); + +Bool +AllocatePicturePrivate (ScreenPtr pScreen, int index2, unsigned int amount); + +Bool +PictureDestroyWindow (WindowPtr pWindow); + +Bool +PictureCloseScreen (int Index, ScreenPtr pScreen); + +void +PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef); + +Bool +PictureInitIndexedFormats (ScreenPtr pScreen); + +Bool +PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel); + +int +PictureGetSubpixelOrder (ScreenPtr pScreen); + +PictFormatPtr +PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp); + +PictFormatPtr +PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual); + +PictFormatPtr +PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format); + +Bool +PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +int +PictureGetFilterId (char *filter, int len, Bool makeit); + +char * +PictureGetFilterName (int id); + +int +PictureAddFilter (ScreenPtr pScreen, + char *filter, + PictFilterValidateParamsProcPtr ValidateParams); + +Bool +PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias); + +Bool +PictureSetDefaultFilters (ScreenPtr pScreen); + +void +PictureResetFilters (ScreenPtr pScreen); + +PictFilterPtr +PictureFindFilter (ScreenPtr pScreen, char *name, int len); + +int +SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams); + +Bool +PictureFinishInit (void); + +void +SetPictureToDefaults (PicturePtr pPicture); + +PicturePtr +AllocatePicture (ScreenPtr pScreen); + +#if 0 +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); +#endif + + +PicturePtr +CreatePicture (Picture pid, + DrawablePtr pDrawable, + PictFormatPtr pFormat, + Mask mask, + XID *list, + ClientPtr client, + int *error); + +int +ChangePicture (PicturePtr pPicture, + Mask vmask, + XID *vlist, + DevUnion *ulist, + ClientPtr client); + +int +SetPictureClipRects (PicturePtr pPicture, + int xOrigin, + int yOrigin, + int nRect, + xRectangle *rects); + +int +SetPictureClipRegion (PicturePtr pPicture, + int xOrigin, + int yOrigin, + RegionPtr pRegion); + +int +SetPictureTransform (PicturePtr pPicture, + PictTransform *transform); + +void +CopyPicture (PicturePtr pSrc, + Mask mask, + PicturePtr pDst); + +void +ValidatePicture(PicturePtr pPicture); + +int +FreePicture (pointer pPicture, + XID pid); + +int +FreePictFormat (pointer pPictFormat, + XID pid); + +void +CompositePicture (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +CompositeGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr lists, + GlyphPtr *glyphs); + +void +CompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void +CompositeTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +void +CompositeTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntriangles, + xTriangle *triangles); + +void +CompositeTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +void +CompositeTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoints, + xPointFixed *points); + +Bool +PictureTransformPoint (PictTransformPtr transform, + PictVectorPtr vector); + +Bool +PictureTransformPoint3d (PictTransformPtr transform, + PictVectorPtr vector); + +void RenderExtensionInit (void); + +Bool +AnimCurInit (ScreenPtr pScreen); + +int +AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor); + +void +AddTraps (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntraps, + xTrap *traps); + +PicturePtr +CreateSolidPicture (Picture pid, + xRenderColor *color, + int *error); + +PicturePtr +CreateLinearGradientPicture (Picture pid, + xPointFixed *p1, + xPointFixed *p2, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +PicturePtr +CreateRadialGradientPicture (Picture pid, + xPointFixed *inner, + xPointFixed *outer, + xFixed innerRadius, + xFixed outerRadius, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +PicturePtr +CreateConicalGradientPicture (Picture pid, + xPointFixed *center, + xFixed angle, + int nStops, + xFixed *stops, + xRenderColor *colors, + int *error); + +#ifdef PANORAMIX +void PanoramiXRenderInit (void); +void PanoramiXRenderReset (void); +#endif + +#endif /* _PICTURESTR_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c new file mode 100644 index 000000000..3d08a3228 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c @@ -0,0 +1,904 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/property.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: property.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef LBX +#include "lbxserve.h" +#include "lbxtags.h" +#endif + +#include "Options.h" +#include "Rootless.h" +#include "Client.h" + +#if defined(LBX) || defined(LBX_COMPAT) +#if 0 /* no header in X11 environment, not used in X11 environment */ +int fWriteToClient(ClientPtr client, int len, char *buf) +{ + return WriteToClient(client, len, buf); +} +#endif +#endif + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(WindowPtr pWin) +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(ClientPtr client) +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XCSECURITY + char action = SecurityCheckPropertyAccess(client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XCSECURITY + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XCSECURITY + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(ClientPtr client) +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + +#ifdef NXAGENT_CLIPBOARD + { + extern WindowPtr nxagentGetClipboardWindow(Atom, WindowPtr); + + pWin = nxagentGetClipboardWindow(stuff->property, NULL); + } + + if (pWin == NULL) +#endif + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + +#ifdef NXAGENT_ARTSD + { + /* Do not process MCOPGLOBALS property changes, + they are already set reflecting the server side settings. + Just return success. + */ + extern Atom mcop_local_atom; + if (stuff->property == mcop_local_atom) + return client->noClientException; + } +#endif + +#ifdef LBX + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL); +#else + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); +#endif + if (err != Success) + return err; + else + { + if (nxagentOption(Rootless) == 1) + { + nxagentExportProperty(pWin, stuff->property, stuff->type, (int) format, + (int) mode, len, (pointer) &stuff[1]); + } + + nxagentGuessClientHint(client, stuff->property, (char *) &stuff[1]); + + nxagentGuessShadowHint(client, stuff->property); + + return client->noClientException; + } +} + +int +ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format, + int mode, unsigned long len, pointer value, + Bool sendevent) +{ +#ifdef LBX + return LbxChangeWindowProperty(NULL, pWin, property, type, + format, mode, len, TRUE, value, + sendevent, NULL); +#else + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +#endif +} + +int +DeleteProperty(WindowPtr pWin, Atom propName) +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(WindowPtr pWin) +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply( + ClientPtr client, + ATOM propertyType, + int format, + xGetPropertyReply *reply) +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(ClientPtr client) +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XCSECURITY + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } +#ifdef LBX + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } +#endif + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; + case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; + default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +#ifdef NXAGENT_CLIPBOARD +/* GetWindowProperty clipboard use only */ +int +GetWindowProperty(pWin, property, longOffset, longLength, delete, + type, actualType, format, nItems, bytesAfter, propData ) + WindowPtr pWin; + Atom property; + long longOffset; + long longLength; + Bool delete; + Atom type; + Atom *actualType; + int *format; + unsigned long *nItems; + unsigned long *bytesAfter; + unsigned char **propData; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + + if (!pWin) + return BadWindow; + + + if (!ValidAtom(property)) + { + return(BadAtom); + } + if ((type != AnyPropertyType) && !ValidAtom(type)) + { + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + + while (pProp) + { + if (pProp->propertyName == property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + + if (!pProp) + return (BadAtom); + + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((type != pProp->type) && + (type != AnyPropertyType)) + ) + { + *bytesAfter = pProp->size; + *format = pProp->format; + *nItems = 0; + *actualType = pProp->type; + return(Success); + } + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + return BadValue; + } + + len = min(n - ind, 4 * longLength); + + *bytesAfter = n - (ind + len); + *format = pProp->format; + *nItems = len / (pProp->format / 8 ); + *actualType = pProp->type; + + if (delete && (*bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + if (len) + { + *propData = (unsigned char *)(pProp->data) + ind; + } + + if (delete && (*bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} +#endif + +int +ProcListProperties(ClientPtr client) +{ + Atom *pAtoms = NULL, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(register ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XCSECURITY + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.NX.original new file mode 100644 index 000000000..3d08a3228 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.NX.original @@ -0,0 +1,904 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/property.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: property.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "../../dix/dispatch.h" +#include "swaprep.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef LBX +#include "lbxserve.h" +#include "lbxtags.h" +#endif + +#include "Options.h" +#include "Rootless.h" +#include "Client.h" + +#if defined(LBX) || defined(LBX_COMPAT) +#if 0 /* no header in X11 environment, not used in X11 environment */ +int fWriteToClient(ClientPtr client, int len, char *buf) +{ + return WriteToClient(client, len, buf); +} +#endif +#endif + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(WindowPtr pWin) +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(ClientPtr client) +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XCSECURITY + char action = SecurityCheckPropertyAccess(client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XCSECURITY + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XCSECURITY + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(ClientPtr client) +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + +#ifdef NXAGENT_CLIPBOARD + { + extern WindowPtr nxagentGetClipboardWindow(Atom, WindowPtr); + + pWin = nxagentGetClipboardWindow(stuff->property, NULL); + } + + if (pWin == NULL) +#endif + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + +#ifdef NXAGENT_ARTSD + { + /* Do not process MCOPGLOBALS property changes, + they are already set reflecting the server side settings. + Just return success. + */ + extern Atom mcop_local_atom; + if (stuff->property == mcop_local_atom) + return client->noClientException; + } +#endif + +#ifdef LBX + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL); +#else + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); +#endif + if (err != Success) + return err; + else + { + if (nxagentOption(Rootless) == 1) + { + nxagentExportProperty(pWin, stuff->property, stuff->type, (int) format, + (int) mode, len, (pointer) &stuff[1]); + } + + nxagentGuessClientHint(client, stuff->property, (char *) &stuff[1]); + + nxagentGuessShadowHint(client, stuff->property); + + return client->noClientException; + } +} + +int +ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format, + int mode, unsigned long len, pointer value, + Bool sendevent) +{ +#ifdef LBX + return LbxChangeWindowProperty(NULL, pWin, property, type, + format, mode, len, TRUE, value, + sendevent, NULL); +#else + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +#endif +} + +int +DeleteProperty(WindowPtr pWin, Atom propName) +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(WindowPtr pWin) +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply( + ClientPtr client, + ATOM propertyType, + int format, + xGetPropertyReply *reply) +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(ClientPtr client) +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XCSECURITY + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } +#ifdef LBX + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } +#endif + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; + case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; + default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +#ifdef NXAGENT_CLIPBOARD +/* GetWindowProperty clipboard use only */ +int +GetWindowProperty(pWin, property, longOffset, longLength, delete, + type, actualType, format, nItems, bytesAfter, propData ) + WindowPtr pWin; + Atom property; + long longOffset; + long longLength; + Bool delete; + Atom type; + Atom *actualType; + int *format; + unsigned long *nItems; + unsigned long *bytesAfter; + unsigned char **propData; +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + + if (!pWin) + return BadWindow; + + + if (!ValidAtom(property)) + { + return(BadAtom); + } + if ((type != AnyPropertyType) && !ValidAtom(type)) + { + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + + while (pProp) + { + if (pProp->propertyName == property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + + if (!pProp) + return (BadAtom); + + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((type != pProp->type) && + (type != AnyPropertyType)) + ) + { + *bytesAfter = pProp->size; + *format = pProp->format; + *nItems = 0; + *actualType = pProp->type; + return(Success); + } + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + return BadValue; + } + + len = min(n - ind, 4 * longLength); + + *bytesAfter = n - (ind + len); + *format = pProp->format; + *nItems = len / (pProp->format / 8 ); + *actualType = pProp->type; + + if (delete && (*bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + if (len) + { + *propData = (unsigned char *)(pProp->data) + ind; + } + + if (delete && (*bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} +#endif + +int +ProcListProperties(ClientPtr client) +{ + Atom *pAtoms = NULL, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(register ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XCSECURITY + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.X.original new file mode 100644 index 000000000..cabe46ecc --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.X.original @@ -0,0 +1,729 @@ +/* $XFree86: xc/programs/Xserver/dix/property.c,v 3.12 2002/02/19 11:09:22 alanh Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $Xorg: property.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include "windowstr.h" +#include "propertyst.h" +#include "dixstruct.h" +#include "dispatch.h" +#include "swaprep.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif +#ifdef LBX +#include "lbxserve.h" +#include "lbxtags.h" +#endif + +#if defined(LBX) || defined(LBX_COMPAT) +#if 0 /* no header in X11 environment, not used in X11 environment */ +int fWriteToClient(ClientPtr client, int len, char *buf) +{ + return WriteToClient(client, len, buf); +} +#endif +#endif + +/***************************************************************** + * Property Stuff + * + * ChangeProperty, DeleteProperty, GetProperties, + * ListProperties + * + * Properties below to windows. A allocate slots each time + * a property is added. No fancy searching done. + * + *****************************************************************/ + +#ifdef notdef +static void +PrintPropertys(WindowPtr pWin) +{ + PropertyPtr pProp; + register int j; + + pProp = pWin->userProps; + while (pProp) + { + ErrorF( "%x %x\n", pProp->propertyName, pProp->type); + ErrorF("property format: %d\n", pProp->format); + ErrorF("property data: \n"); + for (j=0; j<(pProp->format/8)*pProp->size; j++) + ErrorF("%c\n", pProp->data[j]); + pProp = pProp->next; + } +} +#endif + +int +ProcRotateProperties(ClientPtr client) +{ + int i, j, delta; + REQUEST(xRotatePropertiesReq); + WindowPtr pWin; + register Atom * atoms; + PropertyPtr * props; /* array of pointer */ + PropertyPtr pProp; + xEvent event; + + REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!stuff->nAtoms) + return(Success); + atoms = (Atom *) & stuff[1]; + props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr)); + if (!props) + return(BadAlloc); + for (i = 0; i < stuff->nAtoms; i++) + { +#ifdef XCSECURITY + char action = SecurityCheckPropertyAccess(client, pWin, atoms[i], + SecurityReadAccess|SecurityWriteAccess); +#endif + if (!ValidAtom(atoms[i]) +#ifdef XCSECURITY + || (SecurityErrorOperation == action) +#endif + ) + { + DEALLOCATE_LOCAL(props); + client->errorValue = atoms[i]; + return BadAtom; + } +#ifdef XCSECURITY + if (SecurityIgnoreOperation == action) + { + DEALLOCATE_LOCAL(props); + return Success; + } +#endif + for (j = i + 1; j < stuff->nAtoms; j++) + if (atoms[j] == atoms[i]) + { + DEALLOCATE_LOCAL(props); + return BadMatch; + } + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == atoms[i]) + goto found; + pProp = pProp->next; + } + DEALLOCATE_LOCAL(props); + return BadMatch; +found: + props[i] = pProp; + } + delta = stuff->nPositions; + + /* If the rotation is a complete 360 degrees, then moving the properties + around and generating PropertyNotify events should be skipped. */ + + if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) + { + while (delta < 0) /* faster if abs value is small */ + delta += stuff->nAtoms; + for (i = 0; i < stuff->nAtoms; i++) + { + /* Generate a PropertyNotify event for each property whose value + is changed in the order in which they appear in the request. */ + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = props[i]->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + + props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms]; + } + } + DEALLOCATE_LOCAL(props); + return Success; +} + +int +ProcChangeProperty(ClientPtr client) +{ + WindowPtr pWin; + char format, mode; + unsigned long len; + int sizeInBytes; + int totalSize; + int err; + REQUEST(xChangePropertyReq); + + REQUEST_AT_LEAST_SIZE(xChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) + { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) + { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); + + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if (!ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + return Success; + } +#endif + +#ifdef LBX + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL); +#else + err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format, + (int)mode, len, (pointer)&stuff[1], TRUE); +#endif + if (err != Success) + return err; + else + return client->noClientException; +} + +int +ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format, + int mode, unsigned long len, pointer value, + Bool sendevent) +{ +#ifdef LBX + return LbxChangeWindowProperty(NULL, pWin, property, type, + format, mode, len, TRUE, value, + sendevent, NULL); +#else + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format>>3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps (pWin); + while (pProp) + { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) /* just add to list */ + { + if (!pWin->optional && !MakeWindowOptional (pWin)) + return(BadAlloc); + pProp = (PropertyPtr)xalloc(sizeof(PropertyRec)); + if (!pProp) + return(BadAlloc); + data = (pointer)xalloc(totalSize); + if (!data && len) + { + xfree(pProp); + return(BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (len) + memmove((char *)data, (char *)value, totalSize); + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } + else + { + /* To append or prepend to a property the request format and type + must match those of the already defined property. The + existing format and type are irrelevant when using the mode + "PropModeReplace" since they will be written over. */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return(BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return(BadMatch); + if (mode == PropModeReplace) + { + if (totalSize != pProp->size * (pProp->format >> 3)) + { + data = (pointer)xrealloc(pProp->data, totalSize); + if (!data && len) + return(BadAlloc); + pProp->data = data; + } + if (len) + memmove((char *)pProp->data, (char *)value, totalSize); + pProp->size = len; + pProp->type = type; + pProp->format = format; + } + else if (len == 0) + { + /* do nothing */ + } + else if (mode == PropModeAppend) + { + data = (pointer)xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + pProp->data = data; + memmove(&((char *)data)[pProp->size * sizeInBytes], + (char *)value, + totalSize); + pProp->size += len; + } + else if (mode == PropModePrepend) + { + data = (pointer)xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return(BadAlloc); + memmove(&((char *)data)[totalSize], (char *)pProp->data, + (int)(pProp->size * sizeInBytes)); + memmove((char *)data, (char *)value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) + { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + return(Success); +#endif +} + +int +DeleteProperty(WindowPtr pWin, Atom propName) +{ + PropertyPtr pProp, prevProp; + xEvent event; + + if (!(pProp = wUserProps (pWin))) + return(Success); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == propName) + break; + prevProp = pProp; + pProp = pProp->next; + } + if (pProp) + { + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + { + prevProp->next = pProp->next; + } +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + xfree(pProp->data); + xfree(pProp); + } + return(Success); +} + +void +DeleteAllWindowProperties(WindowPtr pWin) +{ + PropertyPtr pProp, pNextProp; + xEvent event; + + pProp = wUserProps (pWin); + while (pProp) + { +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + pNextProp = pProp->next; + xfree(pProp->data); + xfree(pProp); + pProp = pNextProp; + } +} + +static int +NullPropertyReply( + ClientPtr client, + ATOM propertyType, + int format, + xGetPropertyReply *reply) +{ + reply->nItems = 0; + reply->length = 0; + reply->bytesAfter = 0; + reply->propertyType = propertyType; + reply->format = format; + WriteReplyToClient(client, sizeof(xGenericReply), reply); + return(client->noClientException); +} + +/***************** + * GetProperty + * If type Any is specified, returns the property from the specified + * window regardless of its type. If a type is specified, returns the + * property only if its type equals the specified type. + * If delete is True and a property is returned, the property is also + * deleted from the window and a PropertyNotify event is generated on the + * window. + *****************/ + +int +ProcGetProperty(ClientPtr client) +{ + PropertyPtr pProp, prevProp; + unsigned long n, len, ind; + WindowPtr pWin; + xGetPropertyReply reply; + REQUEST(xGetPropertyReq); + + REQUEST_SIZE_MATCH(xGetPropertyReq); + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return BadWindow; + + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return(BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) + { + client->errorValue = stuff->delete; + return(BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + + pProp = wUserProps (pWin); + prevProp = (PropertyPtr)NULL; + while (pProp) + { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) + return NullPropertyReply(client, None, 0, &reply); + +#ifdef XCSECURITY + { + Mask access_mode = SecurityReadAccess; + + if (stuff->delete) + access_mode |= SecurityDestroyAccess; + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + access_mode)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return NullPropertyReply(client, pProp->type, pProp->format, + &reply); + } + } +#endif + /* If the request type and actual type don't match. Return the + property information, but not the data. */ + + if (((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) + ) + { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + return(Success); + } +#ifdef LBX + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } +#endif + +/* + * Return type, format, value to client + */ + n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* If longOffset is invalid such that it causes "len" to + be negative, it's a value error. */ + + if (n < ind) + { + client->errorValue = stuff->longOffset; + return BadValue; + } + + len = min(n - ind, 4 * stuff->longLength); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.length = (len + 3) >> 2; + reply.nItems = len / (pProp->format / 8 ); + reply.propertyType = pProp->type; + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* send the event */ + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr)NULL); + } + + WriteReplyToClient(client, sizeof(xGenericReply), &reply); + if (len) + { + switch (reply.format) { + case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; + case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; + default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; + } + WriteSwappedDataToClient(client, len, + (char *)pProp->data + ind); + } + + if (stuff->delete && (reply.bytesAfter == 0)) + { /* delete the Property */ +#ifdef LBX + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); +#endif + if (prevProp == (PropertyPtr)NULL) /* takes care of head */ + { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed (pWin); + } + else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return(client->noClientException); +} + +int +ProcListProperties(ClientPtr client) +{ + Atom *pAtoms = NULL, *temppAtoms; + xListPropertiesReply xlpr; + int numProps = 0; + WindowPtr pWin; + PropertyPtr pProp; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + + pProp = wUserProps (pWin); + while (pProp) + { + pProp = pProp->next; + numProps++; + } + if (numProps) + if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom)))) + return(BadAlloc); + + xlpr.type = X_Reply; + xlpr.nProperties = numProps; + xlpr.length = (numProps * sizeof(Atom)) >> 2; + xlpr.sequenceNumber = client->sequence; + pProp = wUserProps (pWin); + temppAtoms = pAtoms; + while (pProp) + { + *temppAtoms++ = pProp->propertyName; + pProp = pProp->next; + } + WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); + if (numProps) + { + client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; + WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); + DEALLOCATE_LOCAL(pAtoms); + } + return(client->noClientException); +} + +int +ProcDeleteProperty(register ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xDeletePropertyReq); + int result; + + REQUEST_SIZE_MATCH(xDeletePropertyReq); + UpdateCurrentTime(); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return(BadWindow); + if (!ValidAtom(stuff->property)) + { + client->errorValue = stuff->property; + return (BadAtom); + } + +#ifdef XCSECURITY + switch(SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityDestroyAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom;; + case SecurityIgnoreOperation: + return Success; + } +#endif + + result = DeleteProperty(pWin, stuff->property); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c new file mode 100644 index 000000000..426d15b1b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c @@ -0,0 +1,1344 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $ + * + * Copyright © 2000, Compaq Computer Corporation, + * Copyright © 2002, Hewlett Packard, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + */ + + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include +#include +#include "../../randr/randrstr.h" +#ifdef RENDER +#include /* we share subpixel order information */ +#include "picturestr.h" +#endif +#include +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +/* From render.h */ +#ifndef SubPixelUnknown +#define SubPixelUnknown 0 +#endif + +#define RR_VALIDATE +int RRGeneration; +int RRNScreens; + +static int ProcRRQueryVersion (ClientPtr pClient); +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); +static int SProcRRQueryVersion (ClientPtr pClient); + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +#if 0 +static CARD8 RRReqCode; +static int RRErrBase; +#endif +static int RREventBase; +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static int RRClientPrivateIndex; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +int rrPrivIndex = -1; + +#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +static Bool +RRClientKnowsRates (ClientPtr pClient) +{ + rrClientPriv(pClient); + + return (pRRClient->major_version > 1 || + (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); +} + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static void +RRResetProc (ExtensionEntry *extEntry) +{ +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CloseScreen); + if (pScrPriv->pSizes) + xfree (pScrPriv->pSizes); + xfree (pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); + cpswaps(from->subpixelOrder, to->subpixelOrder); +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (RRGeneration != serverGeneration) + { + if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + RRGeneration = serverGeneration; + } + + pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrSetConfig = 0; + pScrPriv->rrGetInfo = 0; + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScrPriv->rotations = RR_Rotate_0; + + pScrPriv->nSizes = 0; + pScrPriv->nSizesInUse = 0; + pScrPriv->pSizes = 0; + + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->size = -1; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + xfree ((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + RRClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RRClientPrivateIndex, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + ClientType = CreateNewResourceType(RRFreeClient); + if (!ClientType) + return; + EventType = CreateNewResourceType(RRFreeEvents); + if (!EventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + RRResetProc, StandardMinorOpcode); + if (!extEntry) + return; +#if 0 + RRReqCode = (CARD8) extEntry->base; + RRErrBase = extEntry->errorBase; +#endif + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + + return; +} + +int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + xRRScreenChangeNotifyEvent se; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + RRScreenSizePtr pSize; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + + pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType); + if (!pHead) + return WT_WALKCHILDREN; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) pScrPriv->rotation; + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; +#ifdef RENDER + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); +#else + se.subpixelOrder = SubPixelUnknown; +#endif + if (pScrPriv->size >= 0) + { + pSize = &pScrPriv->pSizes[pScrPriv->size]; + se.sizeID = pSize->id; + se.widthInPixels = pSize->width; + se.heightInPixels = pSize->height; + se.widthInMillimeters = pSize->mmWidth; + se.heightInMillimeters = pSize->mmHeight; + } + else + { + /* + * This "shouldn't happen", but a broken DDX can + * forget to set the current configuration on GetInfo + */ + se.sizeID = 0xffff; + se.widthInPixels = 0; + se.heightInPixels = 0; + se.widthInMillimeters = 0; + se.heightInMillimeters = 0; + } + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + se.sequenceNumber = client->sequence; + if(pRREvent->mask & RRScreenChangeNotifyMask) + WriteEventsToClient (client, 1, (xEvent *) &se); + } + return WT_WALKCHILDREN; +} + +Bool +RRGetInfo (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i, j, k, l; + Bool changed; + Rotation rotations; + RRScreenSizePtr pSize; + RRScreenRatePtr pRate; + + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + pSize->oldReferenced = pSize->referenced; + pSize->referenced = FALSE; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + pRate->oldReferenced = pRate->referenced; + pRate->referenced = FALSE; + } + } + if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) + return FALSE; + + changed = FALSE; + + /* + * Check whether anything changed and simultaneously generate + * the protocol id values for the objects + */ + if (rotations != pScrPriv->rotations) + { + pScrPriv->rotations = rotations; + changed = TRUE; + } + + j = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->oldReferenced != pSize->referenced) + changed = TRUE; + if (pSize->referenced) + pSize->id = j++; + l = 0; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + if (pRate->oldReferenced != pRate->referenced) + changed = TRUE; + if (pRate->referenced) + l++; + } + pSize->nRatesInUse = l; + } + pScrPriv->nSizesInUse = j; + if (changed) + { + UpdateCurrentTime (); + pScrPriv->lastConfigTime = currentTime; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + } + return TRUE; +} + +void +RRSendConfigNotify (ScreenPtr pScreen) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + xEvent event; + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = 0; + event.u.configureNotify.y = 0; + + /* XXX xinerama stuff ? */ + + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep; + register int n; + REQUEST(xRRQueryVersionReq); + rrClientPriv(client); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + pRRClient->major_version = stuff->majorVersion; + pRRClient->minor_version = stuff->minorVersion; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RANDR_MAJOR; + rep.minorVersion = RANDR_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +extern char *ConnectionInfo; + +static int padlength[4] = {0, 3, 2, 1}; + +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 int +ProcRRGetScreenInfo (ClientPtr client) +{ + REQUEST(xRRGetScreenInfoReq); + xRRGetScreenInfoReply rep; + WindowPtr pWin; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + unsigned long extraLen; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + + if (!pWin) + return BadWindow; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + if (!pScrPriv) + { + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0;; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nSizes = 0; + rep.sizeID = 0; + rep.rotation = RR_Rotate_0; + rep.rate = 0; + rep.nrateEnts = 0; + extra = 0; + extraLen = 0; + } + else + { + int i, j; + xScreenSizes *size; + CARD16 *rates; + CARD8 *data8; + Bool has_rate = RRClientKnowsRates (client); + + RRGetInfo (pScreen); + + rep.type = X_Reply; + rep.setOfRotations = pScrPriv->rotations; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.rotation = pScrPriv->rotation; + rep.nSizes = pScrPriv->nSizesInUse; + rep.rate = pScrPriv->rate; + rep.nrateEnts = 0; + if (has_rate) + { + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + rep.nrateEnts += (1 + pSize->nRatesInUse); + } + } + } + + if (pScrPriv->size >= 0) + rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id; + else + return BadImplementation; + + extraLen = (rep.nSizes * sizeof (xScreenSizes) + + rep.nrateEnts * sizeof (CARD16)); + + extra = (CARD8 *) xalloc (extraLen); + if (!extra) + return BadAlloc; + /* + * First comes the size information + */ + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + size->widthInPixels = pSize->width; + size->heightInPixels = pSize->height; + size->widthInMillimeters = pSize->mmWidth; + size->heightInMillimeters = pSize->mmHeight; + if (client->swapped) + { + swaps (&size->widthInPixels, n); + swaps (&size->heightInPixels, n); + swaps (&size->widthInMillimeters, n); + swaps (&size->heightInMillimeters, n); + } + size++; + if (has_rate) + { + *rates = pSize->nRatesInUse; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + for (j = 0; j < pSize->nRates; j++) + { + RRScreenRatePtr pRate = &pSize->pRates[j]; + if (pRate->referenced) + { + *rates = pRate->rate; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + } + } + } + } + } + data8 = (CARD8 *) rates; + + if (data8 - (CARD8 *) extra != extraLen) + FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", + (unsigned long)(data8 - (CARD8 *) extra), extraLen); + rep.length = (extraLen + 3) >> 2; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.rotation, n); + swaps(&rep.nSizes, n); + swaps(&rep.sizeID, n); + swaps(&rep.rate, n); + swaps(&rep.nrateEnts, n); + } + WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + xfree (extra); + } + return (client->noClientException); +} + +static int +ProcRRSetScreenConfig (ClientPtr client) +{ + REQUEST(xRRSetScreenConfigReq); + xRRSetScreenConfigReply rep; + DrawablePtr pDraw; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp configTime; + TimeStamp time; + RRScreenSizePtr pSize; + int i; + Rotation rotation; + int rate; + short oldWidth, oldHeight; + Bool has_rate; + + UpdateCurrentTime (); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + has_rate = TRUE; + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + has_rate = FALSE; + } + + SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client, + SecurityWriteAccess); + + pScreen = pDraw->pScreen; + + pScrPriv = rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * if the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated + */ + if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } + + /* + * Search for the requested size + */ + pSize = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced && pSize->id == stuff->sizeID) + { + break; + } + } + if (i == pScrPriv->nSizes) + { + /* + * Invalid size ID + */ + client->errorValue = stuff->sizeID; + return BadValue; + } + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (has_rate) + rate = (int) stuff->rate; + else + rate = 0; + + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + client->errorValue = rate; + return BadValue; + } + } + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + rep.status = RRSetConfigFailed; + goto sendReply; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + pScrPriv->lastSetTime = time; + + /* + * Report Success + */ + rep.status = RRSetConfigSuccess; + +sendReply: + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + swapl(&rep.newConfigTimestamp, n); + swapl(&rep.root, n); + } + WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); + + return (client->noClientException); +} + +int +RRSetScreenConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPrivPtr pScrPriv; + int i; + short oldWidth, oldHeight; + + pScrPriv = rrGetScrPriv(pScreen); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * Validate requested rotation + */ + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + return BadValue; + } + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + return BadImplementation; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + + return Success; +} + +static int +ProcRRSelectInput (ClientPtr client) +{ + REQUEST(xRRSelectInputReq); + rrClientPriv(client); + RRTimesPtr pTimes; + WindowPtr pWin; + RREventPtr pRREvent, pNewRREvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH(xRRSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (RREventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, + SecurityWriteAccess); + + if (stuff->enable & (RRScreenChangeNotifyMask)) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + + if (pHead) + { + /* check for existing entry. */ + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + if (pRREvent->client == client) + return Success; + } + + /* build the entry */ + pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec)); + if (!pNewRREvent) + return BadAlloc; + pNewRREvent->next = 0; + pNewRREvent->client = client; + pNewRREvent->window = pWin; + pNewRREvent->mask = stuff->enable; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewRREvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent)) + 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 = (RREventPtr *) xalloc (sizeof (RREventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewRREvent->next = *pHead; + *pHead = pNewRREvent; + /* + * Now see if the client needs an event + */ + if (pScrPriv) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + TellChanged (pWin, (pointer) pScreen); + } + } + } + else if (stuff->enable == xFalse) + { + /* delete the interest */ + if (pHead) { + pNewRREvent = 0; + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (pRREvent->client == client) + break; + pNewRREvent = pRREvent; + } + if (pRREvent) { + FreeResource (pRREvent->clientResource, ClientType); + if (pNewRREvent) + pNewRREvent->next = pRREvent->next; + else + *pHead = pRREvent->next; + xfree (pRREvent); + } + } + } + else + { + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return ProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return ProcRRSetScreenConfig(client); + case X_RRSelectInput: + return ProcRRSelectInput(client); + case X_RRGetScreenInfo: + return ProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + +static int +SProcRRQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRRQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return ProcRRQueryVersion(client); +} + +static int +SProcRRGetScreenInfo (ClientPtr client) +{ + register int n; + REQUEST(xRRGetScreenInfoReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRGetScreenInfo(client); +} + +static int +SProcRRSetScreenConfig (ClientPtr client) +{ + register int n; + REQUEST(xRRSetScreenConfigReq); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + swaps (&stuff->rate, n); + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + } + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->sizeID, n); + swaps(&stuff->rotation, n); + return ProcRRSetScreenConfig(client); +} + +static int +SProcRRSelectInput (ClientPtr client) +{ + register int n; + REQUEST(xRRSelectInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRSelectInput(client); +} + + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return SProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return SProcRRSetScreenConfig(client); + case X_RRSelectInput: + return SProcRRSelectInput(client); + case X_RRGetScreenInfo: + return SProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + + +static Bool +RRScreenSizeMatches (RRScreenSizePtr a, + RRScreenSizePtr b) +{ + if (a->width != b->width) + return FALSE; + if (a->height != b->height) + return FALSE; + if (a->mmWidth != b->mmWidth) + return FALSE; + if (a->mmHeight != b->mmHeight) + return FALSE; + return TRUE; +} + +RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight) +{ + rrScrPriv (pScreen); + int i; + RRScreenSize tmp; + RRScreenSizePtr pNew; + + if (!pScrPriv) + return 0; + + /* + * FIXME: The compiler reports that field + * id is used uninitialized here. + */ + + tmp.id = 0; + + tmp.width = width; + tmp.height= height; + tmp.mmWidth = mmWidth; + tmp.mmHeight = mmHeight; + tmp.pRates = 0; + tmp.nRates = 0; + tmp.nRatesInUse = 0; + tmp.referenced = TRUE; + tmp.oldReferenced = FALSE; + for (i = 0; i < pScrPriv->nSizes; i++) + if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i])) + { + pScrPriv->pSizes[i].referenced = TRUE; + return &pScrPriv->pSizes[i]; + } + pNew = xrealloc (pScrPriv->pSizes, + (pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); + if (!pNew) + return 0; + pNew[pScrPriv->nSizes++] = tmp; + pScrPriv->pSizes = pNew; + return &pNew[pScrPriv->nSizes-1]; +} + +Bool RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate) +{ + rrScrPriv(pScreen); + int i; + RRScreenRatePtr pNew, pRate; + + if (!pScrPriv) + return FALSE; + + for (i = 0; i < pSize->nRates; i++) + { + pRate = &pSize->pRates[i]; + if (pRate->rate == rate) + { + pRate->referenced = TRUE; + return TRUE; + } + } + + pNew = xrealloc (pSize->pRates, + (pSize->nRates + 1) * sizeof (RRScreenRate)); + if (!pNew) + return FALSE; + pRate = &pNew[pSize->nRates++]; + pRate->rate = rate; + pRate->referenced = TRUE; + pRate->oldReferenced = FALSE; + pSize->pRates = pNew; + return TRUE; +} + +void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + + pScrPriv->rotation = rotation; + pScrPriv->size = pSize - pScrPriv->pSizes; + pScrPriv->rate = rate; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.NX.original new file mode 100644 index 000000000..426d15b1b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.NX.original @@ -0,0 +1,1344 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $ + * + * Copyright © 2000, Compaq Computer Corporation, + * Copyright © 2002, Hewlett Packard, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + */ + + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include +#include +#include "../../randr/randrstr.h" +#ifdef RENDER +#include /* we share subpixel order information */ +#include "picturestr.h" +#endif +#include +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +/* From render.h */ +#ifndef SubPixelUnknown +#define SubPixelUnknown 0 +#endif + +#define RR_VALIDATE +int RRGeneration; +int RRNScreens; + +static int ProcRRQueryVersion (ClientPtr pClient); +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); +static int SProcRRQueryVersion (ClientPtr pClient); + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +#if 0 +static CARD8 RRReqCode; +static int RRErrBase; +#endif +static int RREventBase; +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static int RRClientPrivateIndex; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +int rrPrivIndex = -1; + +#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +static Bool +RRClientKnowsRates (ClientPtr pClient) +{ + rrClientPriv(pClient); + + return (pRRClient->major_version > 1 || + (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); +} + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static void +RRResetProc (ExtensionEntry *extEntry) +{ +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CloseScreen); + if (pScrPriv->pSizes) + xfree (pScrPriv->pSizes); + xfree (pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); + cpswaps(from->subpixelOrder, to->subpixelOrder); +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (RRGeneration != serverGeneration) + { + if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + RRGeneration = serverGeneration; + } + + pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrSetConfig = 0; + pScrPriv->rrGetInfo = 0; + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScrPriv->rotations = RR_Rotate_0; + + pScrPriv->nSizes = 0; + pScrPriv->nSizesInUse = 0; + pScrPriv->pSizes = 0; + + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->size = -1; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + xfree ((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + RRClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RRClientPrivateIndex, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + ClientType = CreateNewResourceType(RRFreeClient); + if (!ClientType) + return; + EventType = CreateNewResourceType(RRFreeEvents); + if (!EventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + RRResetProc, StandardMinorOpcode); + if (!extEntry) + return; +#if 0 + RRReqCode = (CARD8) extEntry->base; + RRErrBase = extEntry->errorBase; +#endif + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + + return; +} + +int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + xRRScreenChangeNotifyEvent se; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + RRScreenSizePtr pSize; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + + pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType); + if (!pHead) + return WT_WALKCHILDREN; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) pScrPriv->rotation; + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; +#ifdef RENDER + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); +#else + se.subpixelOrder = SubPixelUnknown; +#endif + if (pScrPriv->size >= 0) + { + pSize = &pScrPriv->pSizes[pScrPriv->size]; + se.sizeID = pSize->id; + se.widthInPixels = pSize->width; + se.heightInPixels = pSize->height; + se.widthInMillimeters = pSize->mmWidth; + se.heightInMillimeters = pSize->mmHeight; + } + else + { + /* + * This "shouldn't happen", but a broken DDX can + * forget to set the current configuration on GetInfo + */ + se.sizeID = 0xffff; + se.widthInPixels = 0; + se.heightInPixels = 0; + se.widthInMillimeters = 0; + se.heightInMillimeters = 0; + } + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + se.sequenceNumber = client->sequence; + if(pRREvent->mask & RRScreenChangeNotifyMask) + WriteEventsToClient (client, 1, (xEvent *) &se); + } + return WT_WALKCHILDREN; +} + +Bool +RRGetInfo (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i, j, k, l; + Bool changed; + Rotation rotations; + RRScreenSizePtr pSize; + RRScreenRatePtr pRate; + + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + pSize->oldReferenced = pSize->referenced; + pSize->referenced = FALSE; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + pRate->oldReferenced = pRate->referenced; + pRate->referenced = FALSE; + } + } + if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) + return FALSE; + + changed = FALSE; + + /* + * Check whether anything changed and simultaneously generate + * the protocol id values for the objects + */ + if (rotations != pScrPriv->rotations) + { + pScrPriv->rotations = rotations; + changed = TRUE; + } + + j = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->oldReferenced != pSize->referenced) + changed = TRUE; + if (pSize->referenced) + pSize->id = j++; + l = 0; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + if (pRate->oldReferenced != pRate->referenced) + changed = TRUE; + if (pRate->referenced) + l++; + } + pSize->nRatesInUse = l; + } + pScrPriv->nSizesInUse = j; + if (changed) + { + UpdateCurrentTime (); + pScrPriv->lastConfigTime = currentTime; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + } + return TRUE; +} + +void +RRSendConfigNotify (ScreenPtr pScreen) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + xEvent event; + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = 0; + event.u.configureNotify.y = 0; + + /* XXX xinerama stuff ? */ + + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep; + register int n; + REQUEST(xRRQueryVersionReq); + rrClientPriv(client); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + pRRClient->major_version = stuff->majorVersion; + pRRClient->minor_version = stuff->minorVersion; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RANDR_MAJOR; + rep.minorVersion = RANDR_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +extern char *ConnectionInfo; + +static int padlength[4] = {0, 3, 2, 1}; + +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 int +ProcRRGetScreenInfo (ClientPtr client) +{ + REQUEST(xRRGetScreenInfoReq); + xRRGetScreenInfoReply rep; + WindowPtr pWin; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + unsigned long extraLen; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + + if (!pWin) + return BadWindow; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + if (!pScrPriv) + { + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0;; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nSizes = 0; + rep.sizeID = 0; + rep.rotation = RR_Rotate_0; + rep.rate = 0; + rep.nrateEnts = 0; + extra = 0; + extraLen = 0; + } + else + { + int i, j; + xScreenSizes *size; + CARD16 *rates; + CARD8 *data8; + Bool has_rate = RRClientKnowsRates (client); + + RRGetInfo (pScreen); + + rep.type = X_Reply; + rep.setOfRotations = pScrPriv->rotations; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.rotation = pScrPriv->rotation; + rep.nSizes = pScrPriv->nSizesInUse; + rep.rate = pScrPriv->rate; + rep.nrateEnts = 0; + if (has_rate) + { + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + rep.nrateEnts += (1 + pSize->nRatesInUse); + } + } + } + + if (pScrPriv->size >= 0) + rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id; + else + return BadImplementation; + + extraLen = (rep.nSizes * sizeof (xScreenSizes) + + rep.nrateEnts * sizeof (CARD16)); + + extra = (CARD8 *) xalloc (extraLen); + if (!extra) + return BadAlloc; + /* + * First comes the size information + */ + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + size->widthInPixels = pSize->width; + size->heightInPixels = pSize->height; + size->widthInMillimeters = pSize->mmWidth; + size->heightInMillimeters = pSize->mmHeight; + if (client->swapped) + { + swaps (&size->widthInPixels, n); + swaps (&size->heightInPixels, n); + swaps (&size->widthInMillimeters, n); + swaps (&size->heightInMillimeters, n); + } + size++; + if (has_rate) + { + *rates = pSize->nRatesInUse; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + for (j = 0; j < pSize->nRates; j++) + { + RRScreenRatePtr pRate = &pSize->pRates[j]; + if (pRate->referenced) + { + *rates = pRate->rate; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + } + } + } + } + } + data8 = (CARD8 *) rates; + + if (data8 - (CARD8 *) extra != extraLen) + FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", + (unsigned long)(data8 - (CARD8 *) extra), extraLen); + rep.length = (extraLen + 3) >> 2; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.rotation, n); + swaps(&rep.nSizes, n); + swaps(&rep.sizeID, n); + swaps(&rep.rate, n); + swaps(&rep.nrateEnts, n); + } + WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + xfree (extra); + } + return (client->noClientException); +} + +static int +ProcRRSetScreenConfig (ClientPtr client) +{ + REQUEST(xRRSetScreenConfigReq); + xRRSetScreenConfigReply rep; + DrawablePtr pDraw; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp configTime; + TimeStamp time; + RRScreenSizePtr pSize; + int i; + Rotation rotation; + int rate; + short oldWidth, oldHeight; + Bool has_rate; + + UpdateCurrentTime (); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + has_rate = TRUE; + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + has_rate = FALSE; + } + + SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client, + SecurityWriteAccess); + + pScreen = pDraw->pScreen; + + pScrPriv = rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * if the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated + */ + if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } + + /* + * Search for the requested size + */ + pSize = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced && pSize->id == stuff->sizeID) + { + break; + } + } + if (i == pScrPriv->nSizes) + { + /* + * Invalid size ID + */ + client->errorValue = stuff->sizeID; + return BadValue; + } + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (has_rate) + rate = (int) stuff->rate; + else + rate = 0; + + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + client->errorValue = rate; + return BadValue; + } + } + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + rep.status = RRSetConfigFailed; + goto sendReply; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + pScrPriv->lastSetTime = time; + + /* + * Report Success + */ + rep.status = RRSetConfigSuccess; + +sendReply: + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + swapl(&rep.newConfigTimestamp, n); + swapl(&rep.root, n); + } + WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); + + return (client->noClientException); +} + +int +RRSetScreenConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPrivPtr pScrPriv; + int i; + short oldWidth, oldHeight; + + pScrPriv = rrGetScrPriv(pScreen); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * Validate requested rotation + */ + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + return BadValue; + } + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + return BadImplementation; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + + return Success; +} + +static int +ProcRRSelectInput (ClientPtr client) +{ + REQUEST(xRRSelectInputReq); + rrClientPriv(client); + RRTimesPtr pTimes; + WindowPtr pWin; + RREventPtr pRREvent, pNewRREvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH(xRRSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (RREventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, + SecurityWriteAccess); + + if (stuff->enable & (RRScreenChangeNotifyMask)) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + + if (pHead) + { + /* check for existing entry. */ + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + if (pRREvent->client == client) + return Success; + } + + /* build the entry */ + pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec)); + if (!pNewRREvent) + return BadAlloc; + pNewRREvent->next = 0; + pNewRREvent->client = client; + pNewRREvent->window = pWin; + pNewRREvent->mask = stuff->enable; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewRREvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent)) + 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 = (RREventPtr *) xalloc (sizeof (RREventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewRREvent->next = *pHead; + *pHead = pNewRREvent; + /* + * Now see if the client needs an event + */ + if (pScrPriv) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + TellChanged (pWin, (pointer) pScreen); + } + } + } + else if (stuff->enable == xFalse) + { + /* delete the interest */ + if (pHead) { + pNewRREvent = 0; + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (pRREvent->client == client) + break; + pNewRREvent = pRREvent; + } + if (pRREvent) { + FreeResource (pRREvent->clientResource, ClientType); + if (pNewRREvent) + pNewRREvent->next = pRREvent->next; + else + *pHead = pRREvent->next; + xfree (pRREvent); + } + } + } + else + { + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return ProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return ProcRRSetScreenConfig(client); + case X_RRSelectInput: + return ProcRRSelectInput(client); + case X_RRGetScreenInfo: + return ProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + +static int +SProcRRQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRRQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return ProcRRQueryVersion(client); +} + +static int +SProcRRGetScreenInfo (ClientPtr client) +{ + register int n; + REQUEST(xRRGetScreenInfoReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRGetScreenInfo(client); +} + +static int +SProcRRSetScreenConfig (ClientPtr client) +{ + register int n; + REQUEST(xRRSetScreenConfigReq); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + swaps (&stuff->rate, n); + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + } + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->sizeID, n); + swaps(&stuff->rotation, n); + return ProcRRSetScreenConfig(client); +} + +static int +SProcRRSelectInput (ClientPtr client) +{ + register int n; + REQUEST(xRRSelectInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRSelectInput(client); +} + + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return SProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return SProcRRSetScreenConfig(client); + case X_RRSelectInput: + return SProcRRSelectInput(client); + case X_RRGetScreenInfo: + return SProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + + +static Bool +RRScreenSizeMatches (RRScreenSizePtr a, + RRScreenSizePtr b) +{ + if (a->width != b->width) + return FALSE; + if (a->height != b->height) + return FALSE; + if (a->mmWidth != b->mmWidth) + return FALSE; + if (a->mmHeight != b->mmHeight) + return FALSE; + return TRUE; +} + +RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight) +{ + rrScrPriv (pScreen); + int i; + RRScreenSize tmp; + RRScreenSizePtr pNew; + + if (!pScrPriv) + return 0; + + /* + * FIXME: The compiler reports that field + * id is used uninitialized here. + */ + + tmp.id = 0; + + tmp.width = width; + tmp.height= height; + tmp.mmWidth = mmWidth; + tmp.mmHeight = mmHeight; + tmp.pRates = 0; + tmp.nRates = 0; + tmp.nRatesInUse = 0; + tmp.referenced = TRUE; + tmp.oldReferenced = FALSE; + for (i = 0; i < pScrPriv->nSizes; i++) + if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i])) + { + pScrPriv->pSizes[i].referenced = TRUE; + return &pScrPriv->pSizes[i]; + } + pNew = xrealloc (pScrPriv->pSizes, + (pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); + if (!pNew) + return 0; + pNew[pScrPriv->nSizes++] = tmp; + pScrPriv->pSizes = pNew; + return &pNew[pScrPriv->nSizes-1]; +} + +Bool RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate) +{ + rrScrPriv(pScreen); + int i; + RRScreenRatePtr pNew, pRate; + + if (!pScrPriv) + return FALSE; + + for (i = 0; i < pSize->nRates; i++) + { + pRate = &pSize->pRates[i]; + if (pRate->rate == rate) + { + pRate->referenced = TRUE; + return TRUE; + } + } + + pNew = xrealloc (pSize->pRates, + (pSize->nRates + 1) * sizeof (RRScreenRate)); + if (!pNew) + return FALSE; + pRate = &pNew[pSize->nRates++]; + pRate->rate = rate; + pRate->referenced = TRUE; + pRate->oldReferenced = FALSE; + pSize->pRates = pNew; + return TRUE; +} + +void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + + pScrPriv->rotation = rotation; + pScrPriv->size = pSize - pScrPriv->pSizes; + pScrPriv->rate = rate; +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.X.original new file mode 100644 index 000000000..3911a3498 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrandr.c.X.original @@ -0,0 +1,1319 @@ +/* + * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $ + * + * Copyright © 2000, Compaq Computer Corporation, + * Copyright © 2002, Hewlett Packard, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Compaq or HP not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. HP makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + */ + + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include +#include +#include "randrstr.h" +#ifdef RENDER +#include /* we share subpixel order information */ +#include "picturestr.h" +#endif +#include +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +/* From render.h */ +#ifndef SubPixelUnknown +#define SubPixelUnknown 0 +#endif + +#define RR_VALIDATE +int RRGeneration; +int RRNScreens; + +static int ProcRRQueryVersion (ClientPtr pClient); +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); +static int SProcRRQueryVersion (ClientPtr pClient); + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +#if 0 +static CARD8 RRReqCode; +static int RRErrBase; +#endif +static int RREventBase; +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static int RRClientPrivateIndex; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +int rrPrivIndex = -1; + +#define GetRRClient(pClient) ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +static Bool +RRClientKnowsRates (ClientPtr pClient) +{ + rrClientPriv(pClient); + + return (pRRClient->major_version > 1 || + (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); +} + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static void +RRResetProc (ExtensionEntry *extEntry) +{ +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CloseScreen); + if (pScrPriv->pSizes) + xfree (pScrPriv->pSizes); + xfree (pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); + cpswaps(from->subpixelOrder, to->subpixelOrder); +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (RRGeneration != serverGeneration) + { + if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + RRGeneration = serverGeneration; + } + + pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrSetConfig = 0; + pScrPriv->rrGetInfo = 0; + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScrPriv->rotations = RR_Rotate_0; + + pScrPriv->nSizes = 0; + pScrPriv->nSizesInUse = 0; + pScrPriv->pSizes = 0; + + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->size = -1; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + xfree ((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + xfree ((pointer) pCur); + } + xfree ((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + RRClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RRClientPrivateIndex, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + ClientType = CreateNewResourceType(RRFreeClient); + if (!ClientType) + return; + EventType = CreateNewResourceType(RRFreeEvents); + if (!EventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + RRResetProc, StandardMinorOpcode); + if (!extEntry) + return; +#if 0 + RRReqCode = (CARD8) extEntry->base; + RRErrBase = extEntry->errorBase; +#endif + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + + return; +} + +static int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + xRRScreenChangeNotifyEvent se; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + RRScreenSizePtr pSize; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + + pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType); + if (!pHead) + return WT_WALKCHILDREN; + + se.type = RRScreenChangeNotify + RREventBase; + se.rotation = (CARD8) pScrPriv->rotation; + se.timestamp = pScrPriv->lastSetTime.milliseconds; + se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + se.root = pRoot->drawable.id; + se.window = pWin->drawable.id; +#ifdef RENDER + se.subpixelOrder = PictureGetSubpixelOrder (pScreen); +#else + se.subpixelOrder = SubPixelUnknown; +#endif + if (pScrPriv->size >= 0) + { + pSize = &pScrPriv->pSizes[pScrPriv->size]; + se.sizeID = pSize->id; + se.widthInPixels = pSize->width; + se.heightInPixels = pSize->height; + se.widthInMillimeters = pSize->mmWidth; + se.heightInMillimeters = pSize->mmHeight; + } + else + { + /* + * This "shouldn't happen", but a broken DDX can + * forget to set the current configuration on GetInfo + */ + se.sizeID = 0xffff; + se.widthInPixels = 0; + se.heightInPixels = 0; + se.widthInMillimeters = 0; + se.heightInMillimeters = 0; + } + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + se.sequenceNumber = client->sequence; + if(pRREvent->mask & RRScreenChangeNotifyMask) + WriteEventsToClient (client, 1, (xEvent *) &se); + } + return WT_WALKCHILDREN; +} + +static Bool +RRGetInfo (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i, j, k, l; + Bool changed; + Rotation rotations; + RRScreenSizePtr pSize; + RRScreenRatePtr pRate; + + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + pSize->oldReferenced = pSize->referenced; + pSize->referenced = FALSE; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + pRate->oldReferenced = pRate->referenced; + pRate->referenced = FALSE; + } + } + if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) + return FALSE; + + changed = FALSE; + + /* + * Check whether anything changed and simultaneously generate + * the protocol id values for the objects + */ + if (rotations != pScrPriv->rotations) + { + pScrPriv->rotations = rotations; + changed = TRUE; + } + + j = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->oldReferenced != pSize->referenced) + changed = TRUE; + if (pSize->referenced) + pSize->id = j++; + l = 0; + for (k = 0; k < pSize->nRates; k++) + { + pRate = &pSize->pRates[k]; + if (pRate->oldReferenced != pRate->referenced) + changed = TRUE; + if (pRate->referenced) + l++; + } + pSize->nRatesInUse = l; + } + pScrPriv->nSizesInUse = j; + if (changed) + { + UpdateCurrentTime (); + pScrPriv->lastConfigTime = currentTime; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + } + return TRUE; +} + +static void +RRSendConfigNotify (ScreenPtr pScreen) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + xEvent event; + + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = 0; + event.u.configureNotify.y = 0; + + /* XXX xinerama stuff ? */ + + event.u.configureNotify.width = pWin->drawable.width; + event.u.configureNotify.height = pWin->drawable.height; + event.u.configureNotify.borderWidth = wBorderWidth (pWin); + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); +} + +static int +ProcRRQueryVersion (ClientPtr client) +{ + xRRQueryVersionReply rep; + register int n; + REQUEST(xRRQueryVersionReq); + rrClientPriv(client); + + REQUEST_SIZE_MATCH(xRRQueryVersionReq); + pRRClient->major_version = stuff->majorVersion; + pRRClient->minor_version = stuff->minorVersion; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RANDR_MAJOR; + rep.minorVersion = RANDR_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + + +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 int +ProcRRGetScreenInfo (ClientPtr client) +{ + REQUEST(xRRGetScreenInfoReq); + xRRGetScreenInfoReply rep; + WindowPtr pWin; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + CARD8 *extra; + unsigned long extraLen; + + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + + if (!pWin) + return BadWindow; + + pScreen = pWin->drawable.pScreen; + pScrPriv = rrGetScrPriv(pScreen); + rep.pad = 0; + if (!pScrPriv) + { + rep.type = X_Reply; + rep.setOfRotations = RR_Rotate_0;; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = currentTime.milliseconds; + rep.configTimestamp = currentTime.milliseconds; + rep.nSizes = 0; + rep.sizeID = 0; + rep.rotation = RR_Rotate_0; + rep.rate = 0; + rep.nrateEnts = 0; + extra = 0; + extraLen = 0; + } + else + { + int i, j; + xScreenSizes *size; + CARD16 *rates; + CARD8 *data8; + Bool has_rate = RRClientKnowsRates (client); + + RRGetInfo (pScreen); + + rep.type = X_Reply; + rep.setOfRotations = pScrPriv->rotations; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.rotation = pScrPriv->rotation; + rep.nSizes = pScrPriv->nSizesInUse; + rep.rate = pScrPriv->rate; + rep.nrateEnts = 0; + if (has_rate) + { + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + rep.nrateEnts += (1 + pSize->nRatesInUse); + } + } + } + + if (pScrPriv->size >= 0) + rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id; + else + return BadImplementation; + + extraLen = (rep.nSizes * sizeof (xScreenSizes) + + rep.nrateEnts * sizeof (CARD16)); + + extra = (CARD8 *) xalloc (extraLen); + if (!extra) + return BadAlloc; + /* + * First comes the size information + */ + size = (xScreenSizes *) extra; + rates = (CARD16 *) (size + rep.nSizes); + for (i = 0; i < pScrPriv->nSizes; i++) + { + RRScreenSizePtr pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced) + { + size->widthInPixels = pSize->width; + size->heightInPixels = pSize->height; + size->widthInMillimeters = pSize->mmWidth; + size->heightInMillimeters = pSize->mmHeight; + if (client->swapped) + { + swaps (&size->widthInPixels, n); + swaps (&size->heightInPixels, n); + swaps (&size->widthInMillimeters, n); + swaps (&size->heightInMillimeters, n); + } + size++; + if (has_rate) + { + *rates = pSize->nRatesInUse; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + for (j = 0; j < pSize->nRates; j++) + { + RRScreenRatePtr pRate = &pSize->pRates[j]; + if (pRate->referenced) + { + *rates = pRate->rate; + if (client->swapped) + { + swaps (rates, n); + } + rates++; + } + } + } + } + } + data8 = (CARD8 *) rates; + + if (data8 - (CARD8 *) extra != extraLen) + FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n", + (unsigned long)(data8 - (CARD8 *) extra), extraLen); + rep.length = (extraLen + 3) >> 2; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.rotation, n); + swaps(&rep.nSizes, n); + swaps(&rep.sizeID, n); + swaps(&rep.rate, n); + swaps(&rep.nrateEnts, n); + } + WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + xfree (extra); + } + return (client->noClientException); +} + +static int +ProcRRSetScreenConfig (ClientPtr client) +{ + REQUEST(xRRSetScreenConfigReq); + xRRSetScreenConfigReply rep; + DrawablePtr pDraw; + int n; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp configTime; + TimeStamp time; + RRScreenSizePtr pSize; + int i; + Rotation rotation; + int rate; + short oldWidth, oldHeight; + Bool has_rate; + + UpdateCurrentTime (); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + has_rate = TRUE; + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + has_rate = FALSE; + } + + SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client, + SecurityWriteAccess); + + pScreen = pDraw->pScreen; + + pScrPriv = rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * if the client's config timestamp is not the same as the last config + * timestamp, then the config information isn't up-to-date and + * can't even be validated + */ + if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0) + { + rep.status = RRSetConfigInvalidConfigTime; + goto sendReply; + } + + /* + * Search for the requested size + */ + pSize = 0; + for (i = 0; i < pScrPriv->nSizes; i++) + { + pSize = &pScrPriv->pSizes[i]; + if (pSize->referenced && pSize->id == stuff->sizeID) + { + break; + } + } + if (i == pScrPriv->nSizes) + { + /* + * Invalid size ID + */ + client->errorValue = stuff->sizeID; + return BadValue; + } + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (has_rate) + rate = (int) stuff->rate; + else + rate = 0; + + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + client->errorValue = rate; + return BadValue; + } + } + + /* + * Make sure the requested set-time is not older than + * the last set-time + */ + if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0) + { + rep.status = RRSetConfigInvalidTime; + goto sendReply; + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + rep.status = RRSetConfigFailed; + goto sendReply; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + pScrPriv->lastSetTime = time; + + /* + * Report Success + */ + rep.status = RRSetConfigSuccess; + +sendReply: + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds; + rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + swapl(&rep.newConfigTimestamp, n); + swapl(&rep.root, n); + } + WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep); + + return (client->noClientException); +} + +int +RRSetScreenConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPrivPtr pScrPriv; + int i; + short oldWidth, oldHeight; + + pScrPriv = rrGetScrPriv(pScreen); + + oldWidth = pScreen->width; + oldHeight = pScreen->height; + + if (!RRGetInfo (pScreen)) + return BadAlloc; + + /* + * Validate requested rotation + */ + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + return BadValue; + } + + if ((~pScrPriv->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + return BadMatch; + } + + /* + * Validate requested refresh + */ + if (rate) + { + for (i = 0; i < pSize->nRates; i++) + { + RRScreenRatePtr pRate = &pSize->pRates[i]; + if (pRate->referenced && pRate->rate == rate) + break; + } + if (i == pSize->nRates) + { + /* + * Invalid rate + */ + return BadValue; + } + } + + /* + * call out to ddx routine to effect the change + */ + if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, + pSize)) + { + /* + * unknown DDX failure, report to client + */ + return BadImplementation; + } + + /* + * set current extension configuration pointers + */ + RRSetCurrentConfig (pScreen, rotation, rate, pSize); + + /* + * Deliver ScreenChangeNotify events whenever + * the configuration is updated + */ + WalkTree (pScreen, TellChanged, (pointer) pScreen); + + /* + * Deliver ConfigureNotify events when root changes + * pixel size + */ + if (oldWidth != pScreen->width || oldHeight != pScreen->height) + RRSendConfigNotify (pScreen); + RREditConnectionInfo (pScreen); + + /* + * Fix pointer bounds and location + */ + ScreenRestructured (pScreen); + + return Success; +} + +static int +ProcRRSelectInput (ClientPtr client) +{ + REQUEST(xRRSelectInputReq); + rrClientPriv(client); + RRTimesPtr pTimes; + WindowPtr pWin; + RREventPtr pRREvent, pNewRREvent, *pHead; + XID clientResource; + + REQUEST_SIZE_MATCH(xRRSelectInputReq); + pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess); + if (!pWin) + return BadWindow; + pHead = (RREventPtr *)SecurityLookupIDByType(client, + pWin->drawable.id, EventType, + SecurityWriteAccess); + + if (stuff->enable & (RRScreenChangeNotifyMask)) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + + if (pHead) + { + /* check for existing entry. */ + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + if (pRREvent->client == client) + return Success; + } + + /* build the entry */ + pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec)); + if (!pNewRREvent) + return BadAlloc; + pNewRREvent->next = 0; + pNewRREvent->client = client; + pNewRREvent->window = pWin; + pNewRREvent->mask = stuff->enable; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewRREvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent)) + 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 = (RREventPtr *) xalloc (sizeof (RREventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewRREvent->next = *pHead; + *pHead = pNewRREvent; + /* + * Now see if the client needs an event + */ + if (pScrPriv) + { + pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; + if (CompareTimeStamps (pTimes->setTime, + pScrPriv->lastSetTime) != 0 || + CompareTimeStamps (pTimes->configTime, + pScrPriv->lastConfigTime) != 0) + { + TellChanged (pWin, (pointer) pScreen); + } + } + } + else if (stuff->enable == xFalse) + { + /* delete the interest */ + if (pHead) { + pNewRREvent = 0; + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { + if (pRREvent->client == client) + break; + pNewRREvent = pRREvent; + } + if (pRREvent) { + FreeResource (pRREvent->clientResource, ClientType); + if (pNewRREvent) + pNewRREvent->next = pRREvent->next; + else + *pHead = pRREvent->next; + xfree (pRREvent); + } + } + } + else + { + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return ProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return ProcRRSetScreenConfig(client); + case X_RRSelectInput: + return ProcRRSelectInput(client); + case X_RRGetScreenInfo: + return ProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + +static int +SProcRRQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRRQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return ProcRRQueryVersion(client); +} + +static int +SProcRRGetScreenInfo (ClientPtr client) +{ + register int n; + REQUEST(xRRGetScreenInfoReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRGetScreenInfo(client); +} + +static int +SProcRRSetScreenConfig (ClientPtr client) +{ + register int n; + REQUEST(xRRSetScreenConfigReq); + + if (RRClientKnowsRates (client)) + { + REQUEST_SIZE_MATCH (xRRSetScreenConfigReq); + swaps (&stuff->rate, n); + } + else + { + REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq); + } + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + swapl(&stuff->timestamp, n); + swaps(&stuff->sizeID, n); + swaps(&stuff->rotation, n); + return ProcRRSetScreenConfig(client); +} + +static int +SProcRRSelectInput (ClientPtr client) +{ + register int n; + REQUEST(xRRSelectInputReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcRRSelectInput(client); +} + + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_RRQueryVersion: + return SProcRRQueryVersion(client); + case X_RRSetScreenConfig: + return SProcRRSetScreenConfig(client); + case X_RRSelectInput: + return SProcRRSelectInput(client); + case X_RRGetScreenInfo: + return SProcRRGetScreenInfo(client); + default: + return BadRequest; + } +} + + +static Bool +RRScreenSizeMatches (RRScreenSizePtr a, + RRScreenSizePtr b) +{ + if (a->width != b->width) + return FALSE; + if (a->height != b->height) + return FALSE; + if (a->mmWidth != b->mmWidth) + return FALSE; + if (a->mmHeight != b->mmHeight) + return FALSE; + return TRUE; +} + +RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight) +{ + rrScrPriv (pScreen); + int i; + RRScreenSize tmp; + RRScreenSizePtr pNew; + + if (!pScrPriv) + return 0; + + tmp.width = width; + tmp.height= height; + tmp.mmWidth = mmWidth; + tmp.mmHeight = mmHeight; + tmp.pRates = 0; + tmp.nRates = 0; + tmp.nRatesInUse = 0; + tmp.referenced = TRUE; + tmp.oldReferenced = FALSE; + for (i = 0; i < pScrPriv->nSizes; i++) + if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i])) + { + pScrPriv->pSizes[i].referenced = TRUE; + return &pScrPriv->pSizes[i]; + } + pNew = xrealloc (pScrPriv->pSizes, + (pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); + if (!pNew) + return 0; + pNew[pScrPriv->nSizes++] = tmp; + pScrPriv->pSizes = pNew; + return &pNew[pScrPriv->nSizes-1]; +} + +Bool RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate) +{ + rrScrPriv(pScreen); + int i; + RRScreenRatePtr pNew, pRate; + + if (!pScrPriv) + return FALSE; + + for (i = 0; i < pSize->nRates; i++) + { + pRate = &pSize->pRates[i]; + if (pRate->rate == rate) + { + pRate->referenced = TRUE; + return TRUE; + } + } + + pNew = xrealloc (pSize->pRates, + (pSize->nRates + 1) * sizeof (RRScreenRate)); + if (!pNew) + return FALSE; + pRate = &pNew[pSize->nRates++]; + pRate->rate = rate; + pRate->referenced = TRUE; + pRate->oldReferenced = FALSE; + pSize->pRates = pNew; + return TRUE; +} + +void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + rrScrPriv (pScreen); + + if (!pScrPriv) + return; + + pScrPriv->rotation = rotation; + pScrPriv->size = pSize - pScrPriv->pSizes; + pScrPriv->rate = rate; +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c new file mode 100644 index 000000000..00c55cde7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c @@ -0,0 +1,3799 @@ +/* $XdotOrg: xc/programs/Xserver/render/render.c,v 1.12 2005/08/28 19:47:39 ajax Exp $ */ +/* + * $XFree86: xc/programs/Xserver/render/render.c,v 1.27tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include +#include +#include +#include "cursorstr.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#if !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +#include "NXpicturestr.h" +#include "NXglyphstr.h" + +#include "Trap.h" + +#include "Render.h" +#include "Pixmaps.h" +#include "Options.h" +#include "Screen.h" +#include "Cursor.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#ifdef TEST +#include "Literals.h" +#endif + +/* + * From NXmiglyph.c. + */ + +void miGlyphExtents(int nlist, GlyphListPtr list, + GlyphPtr *glyphs, BoxPtr extents); + +/* + * From NXmitrap.c. + */ + +void miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box); + +/* + * Functions from Render.c. + */ + +int nxagentCursorSaveRenderInfo(ScreenPtr, CursorPtr); +void nxagentCursorPostSaveRenderInfo(CursorPtr, ScreenPtr, PicturePtr, int, int); +int nxagentRenderRealizeCursor(ScreenPtr, CursorPtr); +int nxagentCreatePicture(PicturePtr, Mask); +void nxagentDestroyPicture(PicturePtr pPicture); +void nxagentChangePicture(PicturePtr, Mask); +int nxagentChangePictureClip(PicturePtr, int, int, xRectangle *, int, int); +void nxagentComposite(CARD8, PicturePtr, PicturePtr, PicturePtr, INT16, INT16, + INT16, INT16, INT16, INT16, CARD16, CARD16); +void nxagentCompositeRects(CARD8, PicturePtr, xRenderColor *, int, xRectangle *); +void nxagentCreateGlyphSet(GlyphSetPtr glyphSet); +void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet); +void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph); +void nxagentFreeGlyphSet(GlyphSetPtr glyphSet); +void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform); +void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size, + pointer params, int nparams); +void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid *traps); + +/* + * The void pointer is actually a XGlyphElt8. + */ + +void nxagentGlyphs(CARD8, PicturePtr, PicturePtr, PictFormatPtr, + INT16, INT16, int, void *, int, GlyphPtr *); + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); +static int ProcRenderAddTraps (ClientPtr pClient); +static int ProcRenderCreateSolidFill (ClientPtr pClient); +static int ProcRenderCreateLinearGradient (ClientPtr pClient); +static int ProcRenderCreateRadialGradient (ClientPtr pClient); +static int ProcRenderCreateConicalGradient (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); +static int SProcRenderAddTraps (ClientPtr pClient); +static int SProcRenderCreateSolidFill (ClientPtr pClient); +static int SProcRenderCreateLinearGradient (ClientPtr pClient); +static int SProcRenderCreateRadialGradient (ClientPtr pClient); +static int SProcRenderCreateConicalGradient (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, + ProcRenderAddTraps, + ProcRenderCreateSolidFill, + ProcRenderCreateLinearGradient, + ProcRenderCreateRadialGradient, + ProcRenderCreateConicalGradient +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, + SProcRenderAddTraps, + SProcRenderCreateSolidFill, + SProcRenderCreateLinearGradient, + SProcRenderCreateRadialGradient, + SProcRenderCreateConicalGradient +}; + +static void +RenderResetProc (ExtensionEntry *extEntry); + +#if 0 +static CARD8 RenderReqCode; +#endif +int RenderErrBase; +int RenderClientPrivateIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + RenderClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RenderClientPrivateIndex, + sizeof (RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + RenderResetProc, StandardMinorOpcode); + if (!extEntry) + return; +#if 0 + RenderReqCode = (CARD8) extEntry->base; +#endif + RenderErrBase = extEntry->errorBase; +} + +static void +RenderResetProc (ExtensionEntry *extEntry) +{ + ResetPicturePrivateIndex(); + ResetGlyphSetPrivateIndex(); +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = nxagentRenderVersionMajor; + rep.minorVersion = nxagentRenderVersionMinor; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#if 0 +static int +VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + for (v = 0; v < pDepth->numVids; v++) + { + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + } + return 0; +} +#endif + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +extern char *ConnectionInfo; + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; + + extern int nxagentAlphaEnabled; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = nxagentAlphaEnabled ? pFormat->direct.alpha : 0; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + xfree (reply); + return client->noClientException; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + xfree(reply); + return (client->noClientException); +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len; + int error; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityWriteAccess); + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + nxagentCreatePicture(pPicture, stuff -> mask); + + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + int error; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + error = ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); + + nxagentChangePicture(pPicture, stuff->mask); + + return error; +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + int result; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pPicture->pDrawable) + return BadDrawable; + + /* + * The original code used sizeof(xRenderChangePictureReq). + * This was harmless, as both structures have the same size. + * + * nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); + */ + nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq); + if (nr & 4) + return BadLength; + nr >>= 3; + result = SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); + nxagentChangePictureClip (pPicture, + CT_NONE, + nr, + (xRectangle *) &stuff[1], + (int)stuff -> xOrigin, + (int)stuff -> yOrigin); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + nxagentDestroyPicture(pPicture); + + FreeResource (stuff->picture, RT_NONE); + return(client->noClientException); +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + return FALSE; +} + +/* + * Check if both pictures have drawables which are + * virtual pixmaps. See the corresponding define + * in NXpicture.c + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#define nxagentCompositePredicate(pSrc, pDst) TRUE + +#else + +/* + * This is still under development. The final + * goal is to let pictures point to the real + * pixmaps instead of pointing to virtuals. + */ + +int nxagentCompositePredicate(PicturePtr pSrc, PicturePtr pDst) +{ + PixmapPtr pPixmap1; + PixmapPtr pPixmap2; + + pPixmap1 = (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pSrc -> pDrawable) : NULL); + + pPixmap2 = (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pDst -> pDrawable) : NULL); + + if (pPixmap1 == NULL || pPixmap2 == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 0.\n"); + #endif + + return FALSE; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 1.\n"); + #endif + + if (nxagentPixmapIsVirtual(pPixmap1) == 1 && + nxagentPixmapIsVirtual(pPixmap2) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 2.\n"); + #endif + + return TRUE; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 3.\n"); + #endif + + return FALSE; +} + +#endif + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || + (pMask && pMask->pDrawable && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + if (nxagentCompositePredicate(pSrc, pDst)) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pMask, (void *) pDst); + #endif + + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + + #else + + if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP && + pDst -> pDrawable -> type == DRAWABLE_PIXMAP && + (!pMask || pMask -> pDrawable -> type == DRAWABLE_PIXMAP)) + { + PixmapPtr pVirtualPixmapSrc; + PixmapPtr pVirtualPixmapDst; + PixmapPtr pVirtualPixmapMask; + + PicturePtr pVirtualPictureSrc; + PicturePtr pVirtualPictureDst; + PicturePtr pVirtualPictureMask; + + pVirtualPixmapSrc = (PixmapPtr) pSrc -> pDrawable; + pVirtualPictureSrc = nxagentPixmapPriv(pVirtualPixmapSrc) -> pPicture; + + pVirtualPixmapDst = (PixmapPtr) pDst -> pDrawable; + pVirtualPictureDst = nxagentPixmapPriv(pVirtualPixmapDst) -> pPicture; + + if (pMask) + { + pVirtualPixmapMask = (PixmapPtr) pMask -> pDrawable; + pVirtualPictureMask = nxagentPixmapPriv(pVirtualPixmapMask) -> pPicture; + } + else + { + pVirtualPixmapMask = NULL; + pVirtualPictureMask = NULL; + } + + if (pVirtualPictureSrc && pVirtualPictureDst) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pVirtualPixmapSrc, (void *) pVirtualPixmapMask, + (void *) pVirtualPixmapDst); + #endif + + CompositePicture (stuff->op, + pVirtualPictureSrc, + pVirtualPictureMask, + pVirtualPictureDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + } + + #endif + + nxagentComposite (stuff -> op, + pSrc, + pMask, + pDst, + stuff -> xSrc, + stuff -> ySrc, + stuff -> xMask, + stuff -> yMask, + stuff -> xDst, + stuff -> yDst, + stuff -> width, + stuff -> height); + + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + { + if (pFormat != NULL) + { + nxagentTrapezoidExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miTrapezoidBounds (ntraps, (xTrapezoid *) &stuff[1], nxagentTrapezoidExtents); + } + + if (nxagentCompositePredicate(pSrc, pDst) == 1) + { + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + } + + nxagentTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + + if (nxagentTrapezoidExtents != NullBox) + { + xfree(nxagentTrapezoidExtents); + + nxagentTrapezoidExtents = NullBox; + } + } + + return client->noClientException; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + format = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!format) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + + nxagentCreateGlyphSet(glyphSet); + + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->existing, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->existing; + return RenderErrBase + BadGlyphSet; + } + glyphSet->refcnt++; + + nxagentReferenceGlyphSet(glyphSet); + + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return client->noClientException; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityDestroyAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nxagentFreeGlyphSet(glyphSet); + + FreeResource (stuff->glyphset, RT_NONE); + return client->noClientException; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; +} GlyphNewRec, *GlyphNewPtr; + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs; + GlyphPtr glyph = NULL; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + int size; + int err = BadAlloc; + + int totSizeImages; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nglyphs = stuff->nglyphs; + if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec)) + return BadAlloc; + + if (nglyphs <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphNewPtr) Xalloc (nglyphs * sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + totSizeImages = 0; + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + + while (remain >= 0 && nglyphs) + { + glyph = AllocateGlyph (gi, glyphSet->fdepth); + if (!glyph) + { + err = BadAlloc; + goto bail; + } + + glyphs->glyph = glyph; + glyphs->id = *gids; + + size = glyph->size - sizeof (xGlyphInfo); + if (remain < size) + break; + memcpy ((CARD8 *) (glyph + 1), bits, size); + + if (size & 3) + size += 4 - (size & 3); + bits += size; + totSizeImages += size; + remain -= size; + gi++; + gids++; + glyphs++; + nglyphs--; + } + + if (nglyphs || remain) + { + err = BadLength; + goto bail; + } + nglyphs = stuff->nglyphs; + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + glyphs = glyphsBase; + while (nglyphs--) { + AddGlyph (glyphSet, glyphs->glyph, glyphs->id); + glyphs++; + } + + if (glyphsBase != glyphsLocal) + Xfree (glyphsBase); + return client->noClientException; +bail: + while (glyphs != glyphsBase) + { + --glyphs; + xfree (glyphs->glyph); + } + if (glyphsBase != glyphsLocal) + Xfree (glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; + gids = (CARD32 *) (stuff + 1); + + nxagentFreeGlyphs(glyphSet, gids, nglyph); + + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return client->noClientException; +} + +typedef struct XGlyphElt8{ + GlyphSet glyphset; + _Xconst char *chars; + int nchars; + int xOff; + int yOff; +} XGlyphElt8; + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int n; + + XGlyphElt8 *elements, *elementsBase; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + + elementsBase = xalloc(nlist * sizeof(XGlyphElt8)); + if (!elementsBase) + return BadAlloc; + + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + elements = elementsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + #ifdef DEBUG + fprintf(stderr, "ProcRenderCompositeGlyphs: Glyphset change with base size [%d].\n", + size); + #endif + + if (buffer + sizeof (GlyphSet) < end) + { + memcpy(&gs, buffer, sizeof(GlyphSet)); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + gs, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = gs; + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + return RenderErrBase + BadGlyphSet; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + + if (glyphSet -> remoteID == 0) + { + #ifdef TEST + fprintf(stderr, "ProcRenderCompositeGlyphs: Going to reconnect glyphset at [%p].\n", + (void *) glyphSet); + #endif + + nxagentReconnectGlyphSet(glyphSet, (XID) 0, (void*) NULL); + } + + elements -> glyphset = glyphSet -> remoteID; + elements -> chars = (char *) buffer; + elements -> nchars = elt->len; + elements -> xOff = elt->deltax; + elements -> yOff = elt->deltay; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + elements++; + } + } + if (buffer > end) + return BadLength; + + /* + * We need to know the glyphs extents to synchronize + * the drawables involved in the composite text ope- + * ration. Also we need to synchronize only the back- + * ground of the text we are going to render, so the + * operations on the framebuffer must be executed + * after the X requests. + */ + + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents(nlist, listsBase, glyphsBase, nxagentGlyphsExtents); + + nxagentGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + elementsBase, + size, + glyphsBase); + + if (nxagentCompositePredicate(pSrc, pDst) == 1) + { + #ifdef TEST + fprintf(stderr, "ProcRenderCompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + CompositeGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + listsBase, + glyphsBase); + } + + xfree(nxagentGlyphsExtents); + nxagentGlyphsExtents = NullBox; + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + + xfree(elementsBase); + + return client->noClientException; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + ValidatePicture (pDst); + nxagentCompositeRects(stuff -> op, + pDst, + &stuff -> color, + things, + (xRectangle *) &stuff[1]); + + return client->noClientException; +} + +static void +SetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int ncolor; + + RealizeCursorProcPtr saveRealizeCursor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + if (!pSrc->pDrawable) + return BadDrawable; + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = xalloc (width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = (unsigned char *)xalloc(nbytes_mono); + if (!srcbits) + { + xfree (argbbits); + return (BadAlloc); + } + mskbits = (unsigned char *)xalloc(nbytes_mono); + if (!mskbits) + { + xfree(argbbits); + xfree(srcbits); + return (BadAlloc); + } + bzero ((char *) mskbits, nbytes_mono); + bzero ((char *) srcbits, nbytes_mono); + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); + if (!pPixmap) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + SetBit (mskline, x, a != 0); + SetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + SetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + SetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + xfree (argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + + /* + * This cursor uses RENDER, so we make sure + * that it is allocated in a way that allows + * the mi and dix layers to handle it but we + * later create it on the server by mirror- + * ing the RENDER operation we got from the + * client. + */ + + saveRealizeCursor = pScreen -> RealizeCursor; + + pScreen -> RealizeCursor = nxagentCursorSaveRenderInfo; + + pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0)); + + pScreen -> RealizeCursor = saveRealizeCursor; + + /* + * Store into the private data members the + * information needed to recreate it at + * reconnection. This is done in two steps + * as in the first step we don't have the + * picture info. + */ + + if (pCursor == NULL) + { + return BadAlloc; + } + + nxagentCursorPostSaveRenderInfo(pCursor, pScreen, pSrc, stuff -> x, stuff -> y); + + nxagentRenderRealizeCursor(pScreen, pCursor); + + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + int result; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); + + nxagentSetPictureTransform(pPicture, &stuff->transform); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j; + int len; + int total_bytes; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, SecurityReadAccess); + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < (int)reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + xfree (reply); + + return(client->noClientException); +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + name = (char *) (stuff + 1); + params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + + nxagentSetPictureFilter(pPicture, name, stuff->nbytes, params, nparams); + + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; + cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursors[i]) + { + xfree (cursors); + client->errorValue = elt->cursor; + return BadCursor; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); + xfree (cursors); + if (ret != Success) + return ret; + + nxagentAnimCursorBits = pCursor -> bits; + + for (i = 0; i < MAXSCREENS; i++) + { + pCursor -> devPriv[i] = NULL; + } + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + +static int +ProcRenderAddTraps (ClientPtr client) +{ + int ntraps; + PicturePtr pPicture; + REQUEST(xRenderAddTrapsReq); + + REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pPicture->pDrawable) + return BadDrawable; + ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (ntraps % sizeof (xTrap)) + return BadLength; + ntraps /= sizeof (xTrap); + if (ntraps) + AddTraps (pPicture, + stuff->xOff, stuff->yOff, + ntraps, (xTrap *) &stuff[1]); + return client->noClientException; +} + +static int ProcRenderCreateSolidFill(ClientPtr client) +{ + PicturePtr pPicture; + int error = 0; + REQUEST(xRenderCreateSolidFillReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateLinearGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateLinearGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateRadialGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateRadialGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer, + stuff->inner_radius, stuff->outer_radius, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateConicalGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateConicalGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + + +static int +ProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + #ifdef TEST + fprintf(stderr, "ProcRenderDispatch: Request [%s] OPCODE#%d.\n", + nxagentRenderRequestLiteral[stuff->data], stuff->data); + #endif + + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*ProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register unsigned int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddTraps (ClientPtr client) +{ + register int n; + REQUEST (xRenderAddTrapsReq); + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->xOff, n); + swaps(&stuff->yOff, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateSolidFill(ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateSolidFillReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swaps(&stuff->color.alpha, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static void swapStops(void *stuff, int n) +{ + int i; + CARD32 *stops; + CARD16 *colors; + stops = (CARD32 *)(stuff); + for (i = 0; i < n; ++i) { + swapl(stops, n); + ++stops; + } + colors = (CARD16 *)(stops); + for (i = 0; i < 4*n; ++i) { + swaps(stops, n); + ++stops; + } +} + +static int +SProcRenderCreateLinearGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateLinearGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->p1.x, n); + swapl(&stuff->p1.y, n); + swapl(&stuff->p2.x, n); + swapl(&stuff->p2.y, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateRadialGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateRadialGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->inner.x, n); + swapl(&stuff->inner.y, n); + swapl(&stuff->outer.x, n); + swapl(&stuff->outer.y, n); + swapl(&stuff->inner_radius, n); + swapl(&stuff->outer_radius, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateConicalGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateConicalGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->center.x, n); + swapl(&stuff->center.y, n); + swapl(&stuff->angle, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*SProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +unsigned long XRT_PICTURE; + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + xfree(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureFilter (ClientPtr client) +{ + REQUEST(xRenderSetPictureFilterReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTrapezoids(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrapezoidsReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTrapezoid *trap = (xTrapezoid *) (stuff + 1); + int i = extra_len / sizeof (xTrapezoid); + + while (i--) { + trap->top -= y_off; + trap->bottom -= y_off; + trap->left.p1.x -= x_off; + trap->left.p1.y -= y_off; + trap->left.p2.x -= x_off; + trap->left.p2.y -= y_off; + trap->right.p1.x -= x_off; + trap->right.p1.y -= y_off; + trap->right.p2.x -= x_off; + trap->right.p2.y -= y_off; + trap++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriangles(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrianglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTriangle *tri = (xTriangle *) (stuff + 1); + int i = extra_len / sizeof (xTriangle); + + while (i--) { + tri->p1.x -= x_off; + tri->p1.y -= y_off; + tri->p2.x -= x_off; + tri->p2.y -= y_off; + tri->p3.x -= x_off; + tri->p3.y -= y_off; + tri++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriStrip(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriStripReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriStripReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriFan(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriFanReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriFanReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +#if 0 /* Not implemented yet */ + +static int +PanoramiXRenderColorTrapezoids(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderColorTrapezoidsReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderColorTrapezoidsReq); + + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderColorTrapezoidsReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + ....; + } + } + + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderColorTrapezoids]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderColorTriangles(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderColorTrianglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderColorTrianglesReq); + + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderColorTrianglesReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + ....; + } + } + + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderColorTriangles]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +#endif + +static int +PanoramiXRenderAddTraps (ClientPtr client) +{ + PanoramiXRes *picture; + int result = Success, j; + REQUEST(xRenderAddTrapsReq); + char *extra; + int extra_len; + INT16 x_off, y_off; + + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + VERIFY_XIN_PICTURE (picture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + x_off = stuff->xOff; + y_off = stuff->yOff; + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + stuff->picture = picture->info[j].id; + + if (picture->u.pict.root) + { + stuff->xOff = x_off + panoramiXdataPtr[j].x; + stuff->yOff = y_off + panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform; + ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; + + ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids; + ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles; + ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip; + ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan; + ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; +} + +#endif /* PANORAMIX */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.NX.original new file mode 100644 index 000000000..00c55cde7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.NX.original @@ -0,0 +1,3799 @@ +/* $XdotOrg: xc/programs/Xserver/render/render.c,v 1.12 2005/08/28 19:47:39 ajax Exp $ */ +/* + * $XFree86: xc/programs/Xserver/render/render.c,v 1.27tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include +#include +#include +#include "cursorstr.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#if !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +#include "NXpicturestr.h" +#include "NXglyphstr.h" + +#include "Trap.h" + +#include "Render.h" +#include "Pixmaps.h" +#include "Options.h" +#include "Screen.h" +#include "Cursor.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#ifdef TEST +#include "Literals.h" +#endif + +/* + * From NXmiglyph.c. + */ + +void miGlyphExtents(int nlist, GlyphListPtr list, + GlyphPtr *glyphs, BoxPtr extents); + +/* + * From NXmitrap.c. + */ + +void miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box); + +/* + * Functions from Render.c. + */ + +int nxagentCursorSaveRenderInfo(ScreenPtr, CursorPtr); +void nxagentCursorPostSaveRenderInfo(CursorPtr, ScreenPtr, PicturePtr, int, int); +int nxagentRenderRealizeCursor(ScreenPtr, CursorPtr); +int nxagentCreatePicture(PicturePtr, Mask); +void nxagentDestroyPicture(PicturePtr pPicture); +void nxagentChangePicture(PicturePtr, Mask); +int nxagentChangePictureClip(PicturePtr, int, int, xRectangle *, int, int); +void nxagentComposite(CARD8, PicturePtr, PicturePtr, PicturePtr, INT16, INT16, + INT16, INT16, INT16, INT16, CARD16, CARD16); +void nxagentCompositeRects(CARD8, PicturePtr, xRenderColor *, int, xRectangle *); +void nxagentCreateGlyphSet(GlyphSetPtr glyphSet); +void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet); +void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph); +void nxagentFreeGlyphSet(GlyphSetPtr glyphSet); +void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform); +void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size, + pointer params, int nparams); +void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid *traps); + +/* + * The void pointer is actually a XGlyphElt8. + */ + +void nxagentGlyphs(CARD8, PicturePtr, PicturePtr, PictFormatPtr, + INT16, INT16, int, void *, int, GlyphPtr *); + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); +static int ProcRenderAddTraps (ClientPtr pClient); +static int ProcRenderCreateSolidFill (ClientPtr pClient); +static int ProcRenderCreateLinearGradient (ClientPtr pClient); +static int ProcRenderCreateRadialGradient (ClientPtr pClient); +static int ProcRenderCreateConicalGradient (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); +static int SProcRenderAddTraps (ClientPtr pClient); +static int SProcRenderCreateSolidFill (ClientPtr pClient); +static int SProcRenderCreateLinearGradient (ClientPtr pClient); +static int SProcRenderCreateRadialGradient (ClientPtr pClient); +static int SProcRenderCreateConicalGradient (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, + ProcRenderAddTraps, + ProcRenderCreateSolidFill, + ProcRenderCreateLinearGradient, + ProcRenderCreateRadialGradient, + ProcRenderCreateConicalGradient +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, + SProcRenderAddTraps, + SProcRenderCreateSolidFill, + SProcRenderCreateLinearGradient, + SProcRenderCreateRadialGradient, + SProcRenderCreateConicalGradient +}; + +static void +RenderResetProc (ExtensionEntry *extEntry); + +#if 0 +static CARD8 RenderReqCode; +#endif +int RenderErrBase; +int RenderClientPrivateIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + RenderClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RenderClientPrivateIndex, + sizeof (RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + RenderResetProc, StandardMinorOpcode); + if (!extEntry) + return; +#if 0 + RenderReqCode = (CARD8) extEntry->base; +#endif + RenderErrBase = extEntry->errorBase; +} + +static void +RenderResetProc (ExtensionEntry *extEntry) +{ + ResetPicturePrivateIndex(); + ResetGlyphSetPrivateIndex(); +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = nxagentRenderVersionMajor; + rep.minorVersion = nxagentRenderVersionMinor; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#if 0 +static int +VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + for (v = 0; v < pDepth->numVids; v++) + { + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + } + return 0; +} +#endif + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +extern char *ConnectionInfo; + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; + + extern int nxagentAlphaEnabled; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = nxagentAlphaEnabled ? pFormat->direct.alpha : 0; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + xfree (reply); + return client->noClientException; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + xfree(reply); + return (client->noClientException); +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len; + int error; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityWriteAccess); + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + nxagentCreatePicture(pPicture, stuff -> mask); + + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + int error; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + error = ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); + + nxagentChangePicture(pPicture, stuff->mask); + + return error; +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + int result; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pPicture->pDrawable) + return BadDrawable; + + /* + * The original code used sizeof(xRenderChangePictureReq). + * This was harmless, as both structures have the same size. + * + * nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); + */ + nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq); + if (nr & 4) + return BadLength; + nr >>= 3; + result = SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); + nxagentChangePictureClip (pPicture, + CT_NONE, + nr, + (xRectangle *) &stuff[1], + (int)stuff -> xOrigin, + (int)stuff -> yOrigin); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + nxagentDestroyPicture(pPicture); + + FreeResource (stuff->picture, RT_NONE); + return(client->noClientException); +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + return FALSE; +} + +/* + * Check if both pictures have drawables which are + * virtual pixmaps. See the corresponding define + * in NXpicture.c + */ + +#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + +#define nxagentCompositePredicate(pSrc, pDst) TRUE + +#else + +/* + * This is still under development. The final + * goal is to let pictures point to the real + * pixmaps instead of pointing to virtuals. + */ + +int nxagentCompositePredicate(PicturePtr pSrc, PicturePtr pDst) +{ + PixmapPtr pPixmap1; + PixmapPtr pPixmap2; + + pPixmap1 = (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pSrc -> pDrawable) : NULL); + + pPixmap2 = (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? + ((PixmapPtr) pDst -> pDrawable) : NULL); + + if (pPixmap1 == NULL || pPixmap2 == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 0.\n"); + #endif + + return FALSE; + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 1.\n"); + #endif + + if (nxagentPixmapIsVirtual(pPixmap1) == 1 && + nxagentPixmapIsVirtual(pPixmap2) == 1) + { + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 2.\n"); + #endif + + return TRUE; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentCompositePredicate: Case 3.\n"); + #endif + + return FALSE; +} + +#endif + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || + (pMask && pMask->pDrawable && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + + ValidatePicture (pSrc); + if (pMask) + ValidatePicture (pMask); + ValidatePicture (pDst); + + #ifdef NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL + + if (nxagentCompositePredicate(pSrc, pDst)) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pMask, (void *) pDst); + #endif + + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + + #else + + if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP && + pDst -> pDrawable -> type == DRAWABLE_PIXMAP && + (!pMask || pMask -> pDrawable -> type == DRAWABLE_PIXMAP)) + { + PixmapPtr pVirtualPixmapSrc; + PixmapPtr pVirtualPixmapDst; + PixmapPtr pVirtualPixmapMask; + + PicturePtr pVirtualPictureSrc; + PicturePtr pVirtualPictureDst; + PicturePtr pVirtualPictureMask; + + pVirtualPixmapSrc = (PixmapPtr) pSrc -> pDrawable; + pVirtualPictureSrc = nxagentPixmapPriv(pVirtualPixmapSrc) -> pPicture; + + pVirtualPixmapDst = (PixmapPtr) pDst -> pDrawable; + pVirtualPictureDst = nxagentPixmapPriv(pVirtualPixmapDst) -> pPicture; + + if (pMask) + { + pVirtualPixmapMask = (PixmapPtr) pMask -> pDrawable; + pVirtualPictureMask = nxagentPixmapPriv(pVirtualPixmapMask) -> pPicture; + } + else + { + pVirtualPixmapMask = NULL; + pVirtualPictureMask = NULL; + } + + if (pVirtualPictureSrc && pVirtualPictureDst) + { + #ifdef TEST + fprintf(stderr, "ProcRenderComposite: Going to composite with " + "source at [%p] mask at [%p] and destination at [%p].\n", + (void *) pVirtualPixmapSrc, (void *) pVirtualPixmapMask, + (void *) pVirtualPixmapDst); + #endif + + CompositePicture (stuff->op, + pVirtualPictureSrc, + pVirtualPictureMask, + pVirtualPictureDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + } + } + + #endif + + nxagentComposite (stuff -> op, + pSrc, + pMask, + pDst, + stuff -> xSrc, + stuff -> ySrc, + stuff -> xMask, + stuff -> yMask, + stuff -> xDst, + stuff -> yDst, + stuff -> width, + stuff -> height); + + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + { + if (pFormat != NULL) + { + nxagentTrapezoidExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miTrapezoidBounds (ntraps, (xTrapezoid *) &stuff[1], nxagentTrapezoidExtents); + } + + if (nxagentCompositePredicate(pSrc, pDst) == 1) + { + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + } + + nxagentTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + + if (nxagentTrapezoidExtents != NullBox) + { + xfree(nxagentTrapezoidExtents); + + nxagentTrapezoidExtents = NullBox; + } + } + + return client->noClientException; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + format = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!format) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + + nxagentCreateGlyphSet(glyphSet); + + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->existing, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->existing; + return RenderErrBase + BadGlyphSet; + } + glyphSet->refcnt++; + + nxagentReferenceGlyphSet(glyphSet); + + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return client->noClientException; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityDestroyAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nxagentFreeGlyphSet(glyphSet); + + FreeResource (stuff->glyphset, RT_NONE); + return client->noClientException; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; +} GlyphNewRec, *GlyphNewPtr; + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs; + GlyphPtr glyph = NULL; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + int size; + int err = BadAlloc; + + int totSizeImages; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nglyphs = stuff->nglyphs; + if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec)) + return BadAlloc; + + if (nglyphs <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphNewPtr) Xalloc (nglyphs * sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + totSizeImages = 0; + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + + while (remain >= 0 && nglyphs) + { + glyph = AllocateGlyph (gi, glyphSet->fdepth); + if (!glyph) + { + err = BadAlloc; + goto bail; + } + + glyphs->glyph = glyph; + glyphs->id = *gids; + + size = glyph->size - sizeof (xGlyphInfo); + if (remain < size) + break; + memcpy ((CARD8 *) (glyph + 1), bits, size); + + if (size & 3) + size += 4 - (size & 3); + bits += size; + totSizeImages += size; + remain -= size; + gi++; + gids++; + glyphs++; + nglyphs--; + } + + if (nglyphs || remain) + { + err = BadLength; + goto bail; + } + nglyphs = stuff->nglyphs; + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + glyphs = glyphsBase; + while (nglyphs--) { + AddGlyph (glyphSet, glyphs->glyph, glyphs->id); + glyphs++; + } + + if (glyphsBase != glyphsLocal) + Xfree (glyphsBase); + return client->noClientException; +bail: + while (glyphs != glyphsBase) + { + --glyphs; + xfree (glyphs->glyph); + } + if (glyphsBase != glyphsLocal) + Xfree (glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; + gids = (CARD32 *) (stuff + 1); + + nxagentFreeGlyphs(glyphSet, gids, nglyph); + + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return client->noClientException; +} + +typedef struct XGlyphElt8{ + GlyphSet glyphset; + _Xconst char *chars; + int nchars; + int xOff; + int yOff; +} XGlyphElt8; + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int n; + + XGlyphElt8 *elements, *elementsBase; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + + elementsBase = xalloc(nlist * sizeof(XGlyphElt8)); + if (!elementsBase) + return BadAlloc; + + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + elements = elementsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + #ifdef DEBUG + fprintf(stderr, "ProcRenderCompositeGlyphs: Glyphset change with base size [%d].\n", + size); + #endif + + if (buffer + sizeof (GlyphSet) < end) + { + memcpy(&gs, buffer, sizeof(GlyphSet)); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + gs, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = gs; + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + return RenderErrBase + BadGlyphSet; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + + if (glyphSet -> remoteID == 0) + { + #ifdef TEST + fprintf(stderr, "ProcRenderCompositeGlyphs: Going to reconnect glyphset at [%p].\n", + (void *) glyphSet); + #endif + + nxagentReconnectGlyphSet(glyphSet, (XID) 0, (void*) NULL); + } + + elements -> glyphset = glyphSet -> remoteID; + elements -> chars = (char *) buffer; + elements -> nchars = elt->len; + elements -> xOff = elt->deltax; + elements -> yOff = elt->deltay; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + elements++; + } + } + if (buffer > end) + return BadLength; + + /* + * We need to know the glyphs extents to synchronize + * the drawables involved in the composite text ope- + * ration. Also we need to synchronize only the back- + * ground of the text we are going to render, so the + * operations on the framebuffer must be executed + * after the X requests. + */ + + nxagentGlyphsExtents = (BoxPtr) xalloc(sizeof(BoxRec)); + + miGlyphExtents(nlist, listsBase, glyphsBase, nxagentGlyphsExtents); + + nxagentGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + elementsBase, + size, + glyphsBase); + + if (nxagentCompositePredicate(pSrc, pDst) == 1) + { + #ifdef TEST + fprintf(stderr, "ProcRenderCompositeGlyphs: Going to composite glyphs with " + "source at [%p] and destination at [%p].\n", + (void *) pSrc, (void *) pDst); + #endif + + CompositeGlyphs(stuff -> op, + pSrc, + pDst, + pFormat, + stuff -> xSrc, + stuff -> ySrc, + nlist, + listsBase, + glyphsBase); + } + + xfree(nxagentGlyphsExtents); + nxagentGlyphsExtents = NullBox; + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + + xfree(elementsBase); + + return client->noClientException; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + ValidatePicture (pDst); + nxagentCompositeRects(stuff -> op, + pDst, + &stuff -> color, + things, + (xRectangle *) &stuff[1]); + + return client->noClientException; +} + +static void +SetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int ncolor; + + RealizeCursorProcPtr saveRealizeCursor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + if (!pSrc->pDrawable) + return BadDrawable; + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = xalloc (width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = (unsigned char *)xalloc(nbytes_mono); + if (!srcbits) + { + xfree (argbbits); + return (BadAlloc); + } + mskbits = (unsigned char *)xalloc(nbytes_mono); + if (!mskbits) + { + xfree(argbbits); + xfree(srcbits); + return (BadAlloc); + } + bzero ((char *) mskbits, nbytes_mono); + bzero ((char *) srcbits, nbytes_mono); + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); + if (!pPixmap) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + SetBit (mskline, x, a != 0); + SetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + SetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + SetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + xfree (argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + + /* + * This cursor uses RENDER, so we make sure + * that it is allocated in a way that allows + * the mi and dix layers to handle it but we + * later create it on the server by mirror- + * ing the RENDER operation we got from the + * client. + */ + + saveRealizeCursor = pScreen -> RealizeCursor; + + pScreen -> RealizeCursor = nxagentCursorSaveRenderInfo; + + pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0)); + + pScreen -> RealizeCursor = saveRealizeCursor; + + /* + * Store into the private data members the + * information needed to recreate it at + * reconnection. This is done in two steps + * as in the first step we don't have the + * picture info. + */ + + if (pCursor == NULL) + { + return BadAlloc; + } + + nxagentCursorPostSaveRenderInfo(pCursor, pScreen, pSrc, stuff -> x, stuff -> y); + + nxagentRenderRealizeCursor(pScreen, pCursor); + + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + int result; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); + + nxagentSetPictureTransform(pPicture, &stuff->transform); + + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j; + int len; + int total_bytes; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, SecurityReadAccess); + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < (int)reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + xfree (reply); + + return(client->noClientException); +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + name = (char *) (stuff + 1); + params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + + nxagentSetPictureFilter(pPicture, name, stuff->nbytes, params, nparams); + + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; + cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursors[i]) + { + xfree (cursors); + client->errorValue = elt->cursor; + return BadCursor; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); + xfree (cursors); + if (ret != Success) + return ret; + + nxagentAnimCursorBits = pCursor -> bits; + + for (i = 0; i < MAXSCREENS; i++) + { + pCursor -> devPriv[i] = NULL; + } + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + +static int +ProcRenderAddTraps (ClientPtr client) +{ + int ntraps; + PicturePtr pPicture; + REQUEST(xRenderAddTrapsReq); + + REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pPicture->pDrawable) + return BadDrawable; + ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (ntraps % sizeof (xTrap)) + return BadLength; + ntraps /= sizeof (xTrap); + if (ntraps) + AddTraps (pPicture, + stuff->xOff, stuff->yOff, + ntraps, (xTrap *) &stuff[1]); + return client->noClientException; +} + +static int ProcRenderCreateSolidFill(ClientPtr client) +{ + PicturePtr pPicture; + int error = 0; + REQUEST(xRenderCreateSolidFillReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateLinearGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateLinearGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateRadialGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateRadialGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer, + stuff->inner_radius, stuff->outer_radius, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateConicalGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateConicalGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + + +static int +ProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + #ifdef TEST + fprintf(stderr, "ProcRenderDispatch: Request [%s] OPCODE#%d.\n", + nxagentRenderRequestLiteral[stuff->data], stuff->data); + #endif + + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*ProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register unsigned int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddTraps (ClientPtr client) +{ + register int n; + REQUEST (xRenderAddTrapsReq); + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->xOff, n); + swaps(&stuff->yOff, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateSolidFill(ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateSolidFillReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swaps(&stuff->color.alpha, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static void swapStops(void *stuff, int n) +{ + int i; + CARD32 *stops; + CARD16 *colors; + stops = (CARD32 *)(stuff); + for (i = 0; i < n; ++i) { + swapl(stops, n); + ++stops; + } + colors = (CARD16 *)(stops); + for (i = 0; i < 4*n; ++i) { + swaps(stops, n); + ++stops; + } +} + +static int +SProcRenderCreateLinearGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateLinearGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->p1.x, n); + swapl(&stuff->p1.y, n); + swapl(&stuff->p2.x, n); + swapl(&stuff->p2.y, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateRadialGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateRadialGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->inner.x, n); + swapl(&stuff->inner.y, n); + swapl(&stuff->outer.x, n); + swapl(&stuff->outer.y, n); + swapl(&stuff->inner_radius, n); + swapl(&stuff->outer_radius, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateConicalGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateConicalGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->center.x, n); + swapl(&stuff->center.y, n); + swapl(&stuff->angle, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + int result; + + REQUEST(xReq); + + /* + * Let the client fail if we are + * hiding the RENDER extension. + */ + + if (nxagentRenderTrap) + { + return BadRequest; + } + + if (stuff->data < RenderNumberRequests) + { + /* + * Set the nxagentGCTrap flag while + * dispatching a render operation to + * avoid reentrancy in GCOps.c. + */ + + nxagentGCTrap = 1; + + result = (*SProcRenderVector[stuff->data]) (client); + + nxagentGCTrap = 0; + + return result; + } + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +unsigned long XRT_PICTURE; + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + xfree(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureFilter (ClientPtr client) +{ + REQUEST(xRenderSetPictureFilterReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTrapezoids(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrapezoidsReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTrapezoid *trap = (xTrapezoid *) (stuff + 1); + int i = extra_len / sizeof (xTrapezoid); + + while (i--) { + trap->top -= y_off; + trap->bottom -= y_off; + trap->left.p1.x -= x_off; + trap->left.p1.y -= y_off; + trap->left.p2.x -= x_off; + trap->left.p2.y -= y_off; + trap->right.p1.x -= x_off; + trap->right.p1.y -= y_off; + trap->right.p2.x -= x_off; + trap->right.p2.y -= y_off; + trap++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriangles(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrianglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTriangle *tri = (xTriangle *) (stuff + 1); + int i = extra_len / sizeof (xTriangle); + + while (i--) { + tri->p1.x -= x_off; + tri->p1.y -= y_off; + tri->p2.x -= x_off; + tri->p2.y -= y_off; + tri->p3.x -= x_off; + tri->p3.y -= y_off; + tri++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriStrip(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriStripReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriStripReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriFan(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriFanReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriFanReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +#if 0 /* Not implemented yet */ + +static int +PanoramiXRenderColorTrapezoids(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderColorTrapezoidsReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderColorTrapezoidsReq); + + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderColorTrapezoidsReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + ....; + } + } + + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderColorTrapezoids]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderColorTriangles(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderColorTrianglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderColorTrianglesReq); + + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderColorTrianglesReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + ....; + } + } + + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderColorTriangles]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +#endif + +static int +PanoramiXRenderAddTraps (ClientPtr client) +{ + PanoramiXRes *picture; + int result = Success, j; + REQUEST(xRenderAddTrapsReq); + char *extra; + int extra_len; + INT16 x_off, y_off; + + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + VERIFY_XIN_PICTURE (picture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + x_off = stuff->xOff; + y_off = stuff->yOff; + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + stuff->picture = picture->info[j].id; + + if (picture->u.pict.root) + { + stuff->xOff = x_off + panoramiXdataPtr[j].x; + stuff->yOff = y_off + panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform; + ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; + + ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids; + ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles; + ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip; + ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan; + ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; +} + +#endif /* PANORAMIX */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.X.original new file mode 100644 index 000000000..d2759ab10 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.X.original @@ -0,0 +1,3306 @@ +/* $XdotOrg: xc/programs/Xserver/render/render.c,v 1.12 2005/08/28 19:47:39 ajax Exp $ */ +/* + * $XFree86: xc/programs/Xserver/render/render.c,v 1.27tsi Exp $ + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#define NEED_REPLIES +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "colormapst.h" +#include "extnsionst.h" +#include "servermd.h" +#include +#include +#include "picturestr.h" +#include "glyphstr.h" +#include +#include "cursorstr.h" +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#if !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +static int ProcRenderQueryVersion (ClientPtr pClient); +static int ProcRenderQueryPictFormats (ClientPtr pClient); +static int ProcRenderQueryPictIndexValues (ClientPtr pClient); +static int ProcRenderQueryDithers (ClientPtr pClient); +static int ProcRenderCreatePicture (ClientPtr pClient); +static int ProcRenderChangePicture (ClientPtr pClient); +static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int ProcRenderFreePicture (ClientPtr pClient); +static int ProcRenderComposite (ClientPtr pClient); +static int ProcRenderScale (ClientPtr pClient); +static int ProcRenderTrapezoids (ClientPtr pClient); +static int ProcRenderTriangles (ClientPtr pClient); +static int ProcRenderTriStrip (ClientPtr pClient); +static int ProcRenderTriFan (ClientPtr pClient); +static int ProcRenderColorTrapezoids (ClientPtr pClient); +static int ProcRenderColorTriangles (ClientPtr pClient); +static int ProcRenderTransform (ClientPtr pClient); +static int ProcRenderCreateGlyphSet (ClientPtr pClient); +static int ProcRenderReferenceGlyphSet (ClientPtr pClient); +static int ProcRenderFreeGlyphSet (ClientPtr pClient); +static int ProcRenderAddGlyphs (ClientPtr pClient); +static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int ProcRenderFreeGlyphs (ClientPtr pClient); +static int ProcRenderCompositeGlyphs (ClientPtr pClient); +static int ProcRenderFillRectangles (ClientPtr pClient); +static int ProcRenderCreateCursor (ClientPtr pClient); +static int ProcRenderSetPictureTransform (ClientPtr pClient); +static int ProcRenderQueryFilters (ClientPtr pClient); +static int ProcRenderSetPictureFilter (ClientPtr pClient); +static int ProcRenderCreateAnimCursor (ClientPtr pClient); +static int ProcRenderAddTraps (ClientPtr pClient); +static int ProcRenderCreateSolidFill (ClientPtr pClient); +static int ProcRenderCreateLinearGradient (ClientPtr pClient); +static int ProcRenderCreateRadialGradient (ClientPtr pClient); +static int ProcRenderCreateConicalGradient (ClientPtr pClient); + +static int ProcRenderDispatch (ClientPtr pClient); + +static int SProcRenderQueryVersion (ClientPtr pClient); +static int SProcRenderQueryPictFormats (ClientPtr pClient); +static int SProcRenderQueryPictIndexValues (ClientPtr pClient); +static int SProcRenderQueryDithers (ClientPtr pClient); +static int SProcRenderCreatePicture (ClientPtr pClient); +static int SProcRenderChangePicture (ClientPtr pClient); +static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); +static int SProcRenderFreePicture (ClientPtr pClient); +static int SProcRenderComposite (ClientPtr pClient); +static int SProcRenderScale (ClientPtr pClient); +static int SProcRenderTrapezoids (ClientPtr pClient); +static int SProcRenderTriangles (ClientPtr pClient); +static int SProcRenderTriStrip (ClientPtr pClient); +static int SProcRenderTriFan (ClientPtr pClient); +static int SProcRenderColorTrapezoids (ClientPtr pClient); +static int SProcRenderColorTriangles (ClientPtr pClient); +static int SProcRenderTransform (ClientPtr pClient); +static int SProcRenderCreateGlyphSet (ClientPtr pClient); +static int SProcRenderReferenceGlyphSet (ClientPtr pClient); +static int SProcRenderFreeGlyphSet (ClientPtr pClient); +static int SProcRenderAddGlyphs (ClientPtr pClient); +static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); +static int SProcRenderFreeGlyphs (ClientPtr pClient); +static int SProcRenderCompositeGlyphs (ClientPtr pClient); +static int SProcRenderFillRectangles (ClientPtr pClient); +static int SProcRenderCreateCursor (ClientPtr pClient); +static int SProcRenderSetPictureTransform (ClientPtr pClient); +static int SProcRenderQueryFilters (ClientPtr pClient); +static int SProcRenderSetPictureFilter (ClientPtr pClient); +static int SProcRenderCreateAnimCursor (ClientPtr pClient); +static int SProcRenderAddTraps (ClientPtr pClient); +static int SProcRenderCreateSolidFill (ClientPtr pClient); +static int SProcRenderCreateLinearGradient (ClientPtr pClient); +static int SProcRenderCreateRadialGradient (ClientPtr pClient); +static int SProcRenderCreateConicalGradient (ClientPtr pClient); + +static int SProcRenderDispatch (ClientPtr pClient); + +int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { + ProcRenderQueryVersion, + ProcRenderQueryPictFormats, + ProcRenderQueryPictIndexValues, + ProcRenderQueryDithers, + ProcRenderCreatePicture, + ProcRenderChangePicture, + ProcRenderSetPictureClipRectangles, + ProcRenderFreePicture, + ProcRenderComposite, + ProcRenderScale, + ProcRenderTrapezoids, + ProcRenderTriangles, + ProcRenderTriStrip, + ProcRenderTriFan, + ProcRenderColorTrapezoids, + ProcRenderColorTriangles, + ProcRenderTransform, + ProcRenderCreateGlyphSet, + ProcRenderReferenceGlyphSet, + ProcRenderFreeGlyphSet, + ProcRenderAddGlyphs, + ProcRenderAddGlyphsFromPicture, + ProcRenderFreeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderCompositeGlyphs, + ProcRenderFillRectangles, + ProcRenderCreateCursor, + ProcRenderSetPictureTransform, + ProcRenderQueryFilters, + ProcRenderSetPictureFilter, + ProcRenderCreateAnimCursor, + ProcRenderAddTraps, + ProcRenderCreateSolidFill, + ProcRenderCreateLinearGradient, + ProcRenderCreateRadialGradient, + ProcRenderCreateConicalGradient +}; + +int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { + SProcRenderQueryVersion, + SProcRenderQueryPictFormats, + SProcRenderQueryPictIndexValues, + SProcRenderQueryDithers, + SProcRenderCreatePicture, + SProcRenderChangePicture, + SProcRenderSetPictureClipRectangles, + SProcRenderFreePicture, + SProcRenderComposite, + SProcRenderScale, + SProcRenderTrapezoids, + SProcRenderTriangles, + SProcRenderTriStrip, + SProcRenderTriFan, + SProcRenderColorTrapezoids, + SProcRenderColorTriangles, + SProcRenderTransform, + SProcRenderCreateGlyphSet, + SProcRenderReferenceGlyphSet, + SProcRenderFreeGlyphSet, + SProcRenderAddGlyphs, + SProcRenderAddGlyphsFromPicture, + SProcRenderFreeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderCompositeGlyphs, + SProcRenderFillRectangles, + SProcRenderCreateCursor, + SProcRenderSetPictureTransform, + SProcRenderQueryFilters, + SProcRenderSetPictureFilter, + SProcRenderCreateAnimCursor, + SProcRenderAddTraps, + SProcRenderCreateSolidFill, + SProcRenderCreateLinearGradient, + SProcRenderCreateRadialGradient, + SProcRenderCreateConicalGradient +}; + +static void +RenderResetProc (ExtensionEntry *extEntry); + +#if 0 +static CARD8 RenderReqCode; +#endif +int RenderErrBase; +int RenderClientPrivateIndex; + +typedef struct _RenderClient { + int major_version; + int minor_version; +} RenderClientRec, *RenderClientPtr; + +#define GetRenderClient(pClient) ((RenderClientPtr) (pClient)->devPrivates[RenderClientPrivateIndex].ptr) + +static void +RenderClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + RenderClientPtr pRenderClient = GetRenderClient (pClient); + + pRenderClient->major_version = 0; + pRenderClient->minor_version = 0; +} + +void +RenderExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (!PictureType) + return; + if (!PictureFinishInit ()) + return; + RenderClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (RenderClientPrivateIndex, + sizeof (RenderClientRec))) + return; + if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) + return; + + extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, + ProcRenderDispatch, SProcRenderDispatch, + RenderResetProc, StandardMinorOpcode); + if (!extEntry) + return; +#if 0 + RenderReqCode = (CARD8) extEntry->base; +#endif + RenderErrBase = extEntry->errorBase; +} + +static void +RenderResetProc (ExtensionEntry *extEntry) +{ + ResetPicturePrivateIndex(); + ResetGlyphSetPrivateIndex(); +} + +static int +ProcRenderQueryVersion (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryVersionReply rep; + register int n; + REQUEST(xRenderQueryVersionReq); + + pRenderClient->major_version = stuff->majorVersion; + pRenderClient->minor_version = stuff->minorVersion; + + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RENDER_MAJOR; + rep.minorVersion = RENDER_MINOR; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +#if 0 +static int +VisualDepth (ScreenPtr pScreen, VisualPtr pVisual) +{ + DepthPtr pDepth; + int d, v; + + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + for (v = 0; v < pDepth->numVids; v++) + { + if (pDepth->vids[v] == pVisual->vid) + return pDepth->depth; + } + } + return 0; +} +#endif + +static VisualPtr +findVisual (ScreenPtr pScreen, VisualID vid) +{ + VisualPtr pVisual; + int v; + + for (v = 0; v < pScreen->numVisuals; v++) + { + pVisual = pScreen->visuals + v; + if (pVisual->vid == vid) + return pVisual; + } + return 0; +} + +extern char *ConnectionInfo; + +static int +ProcRenderQueryPictFormats (ClientPtr client) +{ + RenderClientPtr pRenderClient = GetRenderClient (client); + xRenderQueryPictFormatsReply *reply; + xPictScreen *pictScreen; + xPictDepth *pictDepth; + xPictVisual *pictVisual; + xPictFormInfo *pictForm; + CARD32 *pictSubpixel; + ScreenPtr pScreen; + VisualPtr pVisual; + DepthPtr pDepth; + int v, d; + PictureScreenPtr ps; + PictFormatPtr pFormat; + int nformat; + int ndepth; + int nvisual; + int rlength; + int s; + int n; + int numScreens; + int numSubpixel; +/* REQUEST(xRenderQueryPictFormatsReq); */ + + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); + +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#else + numScreens = screenInfo.numScreens; +#endif + ndepth = nformat = nvisual = 0; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + for (d = 0; d < pScreen->numDepths; d++) + { + pDepth = pScreen->allowedDepths + d; + ++ndepth; + + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) + ++nvisual; + } + } + ps = GetPictureScreenIfSet(pScreen); + if (ps) + nformat += ps->nformats; + } + if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) + numSubpixel = 0; + else + numSubpixel = numScreens; + + rlength = (sizeof (xRenderQueryPictFormatsReply) + + nformat * sizeof (xPictFormInfo) + + numScreens * sizeof (xPictScreen) + + ndepth * sizeof (xPictDepth) + + nvisual * sizeof (xPictVisual) + + numSubpixel * sizeof (CARD32)); + reply = (xRenderQueryPictFormatsReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numFormats = nformat; + reply->numScreens = numScreens; + reply->numDepths = ndepth; + reply->numVisuals = nvisual; + reply->numSubpixel = numSubpixel; + + pictForm = (xPictFormInfo *) (reply + 1); + + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (nformat = 0, pFormat = ps->formats; + nformat < ps->nformats; + nformat++, pFormat++) + { + pictForm->id = pFormat->id; + pictForm->type = pFormat->type; + pictForm->depth = pFormat->depth; + pictForm->direct.red = pFormat->direct.red; + pictForm->direct.redMask = pFormat->direct.redMask; + pictForm->direct.green = pFormat->direct.green; + pictForm->direct.greenMask = pFormat->direct.greenMask; + pictForm->direct.blue = pFormat->direct.blue; + pictForm->direct.blueMask = pFormat->direct.blueMask; + pictForm->direct.alpha = pFormat->direct.alpha; + pictForm->direct.alphaMask = pFormat->direct.alphaMask; + if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) + pictForm->colormap = pFormat->index.pColormap->mid; + else + pictForm->colormap = None; + if (client->swapped) + { + swapl (&pictForm->id, n); + swaps (&pictForm->direct.red, n); + swaps (&pictForm->direct.redMask, n); + swaps (&pictForm->direct.green, n); + swaps (&pictForm->direct.greenMask, n); + swaps (&pictForm->direct.blue, n); + swaps (&pictForm->direct.blueMask, n); + swaps (&pictForm->direct.alpha, n); + swaps (&pictForm->direct.alphaMask, n); + swapl (&pictForm->colormap, n); + } + pictForm++; + } + } + } + + pictScreen = (xPictScreen *) pictForm; + for (s = 0; s < numScreens; s++) + { + pScreen = screenInfo.screens[s]; + pictDepth = (xPictDepth *) (pictScreen + 1); + ndepth = 0; + for (d = 0; d < pScreen->numDepths; d++) + { + pictVisual = (xPictVisual *) (pictDepth + 1); + pDepth = pScreen->allowedDepths + d; + + nvisual = 0; + for (v = 0; v < pDepth->numVids; v++) + { + pVisual = findVisual (pScreen, pDepth->vids[v]); + if (pVisual && (pFormat = PictureMatchVisual (pScreen, + pDepth->depth, + pVisual))) + { + pictVisual->visual = pVisual->vid; + pictVisual->format = pFormat->id; + if (client->swapped) + { + swapl (&pictVisual->visual, n); + swapl (&pictVisual->format, n); + } + pictVisual++; + nvisual++; + } + } + pictDepth->depth = pDepth->depth; + pictDepth->nPictVisuals = nvisual; + if (client->swapped) + { + swaps (&pictDepth->nPictVisuals, n); + } + ndepth++; + pictDepth = (xPictDepth *) pictVisual; + } + pictScreen->nDepth = ndepth; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + pictScreen->fallback = ps->fallback->id; + else + pictScreen->fallback = 0; + if (client->swapped) + { + swapl (&pictScreen->nDepth, n); + swapl (&pictScreen->fallback, n); + } + pictScreen = (xPictScreen *) pictDepth; + } + pictSubpixel = (CARD32 *) pictScreen; + + for (s = 0; s < numSubpixel; s++) + { + pScreen = screenInfo.screens[s]; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + *pictSubpixel = ps->subpixel; + else + *pictSubpixel = SubPixelUnknown; + if (client->swapped) + { + swapl (pictSubpixel, n); + } + ++pictSubpixel; + } + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numFormats, n); + swapl (&reply->numScreens, n); + swapl (&reply->numDepths, n); + swapl (&reply->numVisuals, n); + swapl (&reply->numSubpixel, n); + } + WriteToClient(client, rlength, (char *) reply); + xfree (reply); + return client->noClientException; +} + +static int +ProcRenderQueryPictIndexValues (ClientPtr client) +{ + PictFormatPtr pFormat; + int num; + int rlength; + int i, n; + REQUEST(xRenderQueryPictIndexValuesReq); + xRenderQueryPictIndexValuesReply *reply; + xIndexValue *values; + + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); + + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->type != PictTypeIndexed) + { + client->errorValue = stuff->format; + return BadMatch; + } + num = pFormat->index.nvalues; + rlength = (sizeof (xRenderQueryPictIndexValuesReply) + + num * sizeof(xIndexValue)); + reply = (xRenderQueryPictIndexValuesReply *) xalloc (rlength); + if (!reply) + return BadAlloc; + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = (rlength - sizeof(xGenericReply)) >> 2; + reply->numIndexValues = num; + + values = (xIndexValue *) (reply + 1); + + memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); + + if (client->swapped) + { + for (i = 0; i < num; i++) + { + swapl (&values[i].pixel, n); + swaps (&values[i].red, n); + swaps (&values[i].green, n); + swaps (&values[i].blue, n); + swaps (&values[i].alpha, n); + } + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + swapl (&reply->numIndexValues, n); + } + + WriteToClient(client, rlength, (char *) reply); + xfree(reply); + return (client->noClientException); +} + +static int +ProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreatePicture (ClientPtr client) +{ + PicturePtr pPicture; + DrawablePtr pDrawable; + PictFormatPtr pFormat; + int len; + int error; + REQUEST(xRenderCreatePictureReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, + SecurityWriteAccess); + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + if (pFormat->depth != pDrawable->depth) + return BadMatch; + len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + pPicture = CreatePicture (stuff->pid, + pDrawable, + pFormat, + stuff->mask, + (XID *) (stuff + 1), + client, + &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int +ProcRenderChangePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderChangePictureReq); + int len; + + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2); + if (Ones(stuff->mask) != len) + return BadLength; + + return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), + (DevUnion *) 0, client); +} + +static int +ProcRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + PicturePtr pPicture; + int nr; + int result; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pPicture->pDrawable) + return BadDrawable; + + nr = (client->req_len << 2) - sizeof(xRenderChangePictureReq); + if (nr & 4) + return BadLength; + nr >>= 3; + result = SetPictureClipRects (pPicture, + stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *) &stuff[1]); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderFreePicture (ClientPtr client) +{ + PicturePtr pPicture; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + FreeResource (stuff->picture, RT_NONE); + return(client->noClientException); +} + +static Bool +PictOpValid (CARD8 op) +{ + if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) + return TRUE; + if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) + return TRUE; + if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) + return TRUE; + return FALSE; +} + +static int +ProcRenderComposite (ClientPtr client) +{ + PicturePtr pSrc, pMask, pDst; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_ALPHA (pMask, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || + (pMask && pMask->pDrawable && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen)) + return BadMatch; + CompositePicture (stuff->op, + pSrc, + pMask, + pDst, + stuff->xSrc, + stuff->ySrc, + stuff->xMask, + stuff->yMask, + stuff->xDst, + stuff->yDst, + stuff->width, + stuff->height); + return Success; +} + +static int +ProcRenderScale (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTrapezoids (ClientPtr client) +{ + int ntraps; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + if (ntraps % sizeof (xTrapezoid)) + return BadLength; + ntraps /= sizeof (xTrapezoid); + if (ntraps) + CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntraps, (xTrapezoid *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriangles (ClientPtr client) +{ + int ntris; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + if (ntris % sizeof (xTriangle)) + return BadLength; + ntris /= sizeof (xTriangle); + if (ntris) + CompositeTriangles (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + ntris, (xTriangle *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriStrip (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderTriFan (ClientPtr client) +{ + int npoints; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); + if (npoints & 4) + return(BadLength); + npoints >>= 3; + if (npoints >= 3) + CompositeTriFan (stuff->op, pSrc, pDst, pFormat, + stuff->xSrc, stuff->ySrc, + npoints, (xPointFixed *) &stuff[1]); + return client->noClientException; +} + +static int +ProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderCreateGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + PictFormatPtr format; + int f; + REQUEST(xRenderCreateGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + format = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->format, + PictFormatType, + SecurityReadAccess); + if (!format) + { + client->errorValue = stuff->format; + return RenderErrBase + BadPictFormat; + } + switch (format->depth) { + case 1: + f = GlyphFormat1; + break; + case 4: + f = GlyphFormat4; + break; + case 8: + f = GlyphFormat8; + break; + case 16: + f = GlyphFormat16; + break; + case 32: + f = GlyphFormat32; + break; + default: + return BadMatch; + } + if (format->type != PictTypeDirect) + return BadMatch; + glyphSet = AllocateGlyphSet (f, format); + if (!glyphSet) + return BadAlloc; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return Success; +} + +static int +ProcRenderReferenceGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderReferenceGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); + + LEGAL_NEW_RESOURCE(stuff->gsid, client); + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->existing, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->existing; + return RenderErrBase + BadGlyphSet; + } + glyphSet->refcnt++; + if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) + return BadAlloc; + return client->noClientException; +} + +#define NLOCALDELTA 64 +#define NLOCALGLYPH 256 + +static int +ProcRenderFreeGlyphSet (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderFreeGlyphSetReq); + + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityDestroyAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + FreeResource (stuff->glyphset, RT_NONE); + return client->noClientException; +} + +typedef struct _GlyphNew { + Glyph id; + GlyphPtr glyph; +} GlyphNewRec, *GlyphNewPtr; + +static int +ProcRenderAddGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + REQUEST(xRenderAddGlyphsReq); + GlyphNewRec glyphsLocal[NLOCALGLYPH]; + GlyphNewPtr glyphsBase, glyphs; + GlyphPtr glyph; + int remain, nglyphs; + CARD32 *gids; + xGlyphInfo *gi; + CARD8 *bits; + int size; + int err = BadAlloc; + + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + nglyphs = stuff->nglyphs; + if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec)) + return BadAlloc; + + if (nglyphs <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphNewPtr) Xalloc (nglyphs * sizeof (GlyphNewRec)); + if (!glyphsBase) + return BadAlloc; + } + + remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); + + glyphs = glyphsBase; + + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + nglyphs); + bits = (CARD8 *) (gi + nglyphs); + remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; + while (remain >= 0 && nglyphs) + { + glyph = AllocateGlyph (gi, glyphSet->fdepth); + if (!glyph) + { + err = BadAlloc; + goto bail; + } + + glyphs->glyph = glyph; + glyphs->id = *gids; + + size = glyph->size - sizeof (xGlyphInfo); + if (remain < size) + break; + memcpy ((CARD8 *) (glyph + 1), bits, size); + + if (size & 3) + size += 4 - (size & 3); + bits += size; + remain -= size; + gi++; + gids++; + glyphs++; + nglyphs--; + } + if (nglyphs || remain) + { + err = BadLength; + goto bail; + } + nglyphs = stuff->nglyphs; + if (!ResizeGlyphSet (glyphSet, nglyphs)) + { + err = BadAlloc; + goto bail; + } + glyphs = glyphsBase; + while (nglyphs--) { + AddGlyph (glyphSet, glyphs->glyph, glyphs->id); + glyphs++; + } + + if (glyphsBase != glyphsLocal) + Xfree (glyphsBase); + return client->noClientException; +bail: + while (glyphs != glyphsBase) + { + --glyphs; + xfree (glyphs->glyph); + } + if (glyphsBase != glyphsLocal) + Xfree (glyphsBase); + return err; +} + +static int +ProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +ProcRenderFreeGlyphs (ClientPtr client) +{ + REQUEST(xRenderFreeGlyphsReq); + GlyphSetPtr glyphSet; + int nglyph; + CARD32 *gids; + CARD32 glyph; + + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityWriteAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2; + gids = (CARD32 *) (stuff + 1); + while (nglyph-- > 0) + { + glyph = *gids++; + if (!DeleteGlyph (glyphSet, glyph)) + { + client->errorValue = glyph; + return RenderErrBase + BadGlyph; + } + } + return client->noClientException; +} + +static int +ProcRenderCompositeGlyphs (ClientPtr client) +{ + GlyphSetPtr glyphSet; + GlyphSet gs; + PicturePtr pSrc, pDst; + PictFormatPtr pFormat; + GlyphListRec listsLocal[NLOCALDELTA]; + GlyphListPtr lists, listsBase; + GlyphPtr glyphsLocal[NLOCALGLYPH]; + Glyph glyph; + GlyphPtr *glyphs, *glyphsBase; + xGlyphElt *elt; + CARD8 *buffer, *end; + int nglyph; + int nlist; + int space; + int size; + int n; + + REQUEST(xRenderCompositeGlyphsReq); + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) + return BadMatch; + if (stuff->maskFormat) + { + pFormat = (PictFormatPtr) SecurityLookupIDByType (client, + stuff->maskFormat, + PictFormatType, + SecurityReadAccess); + if (!pFormat) + { + client->errorValue = stuff->maskFormat; + return RenderErrBase + BadPictFormat; + } + } + else + pFormat = 0; + + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + stuff->glyphset, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = stuff->glyphset; + return RenderErrBase + BadGlyphSet; + } + + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + nglyph = 0; + nlist = 0; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + buffer += 4; + } + else + { + nlist++; + nglyph += elt->len; + space = size * elt->len; + if (space & 3) + space += 4 - (space & 3); + buffer += space; + } + } + if (nglyph <= NLOCALGLYPH) + glyphsBase = glyphsLocal; + else + { + glyphsBase = (GlyphPtr *) ALLOCATE_LOCAL (nglyph * sizeof (GlyphPtr)); + if (!glyphsBase) + return BadAlloc; + } + if (nlist <= NLOCALDELTA) + listsBase = listsLocal; + else + { + listsBase = (GlyphListPtr) ALLOCATE_LOCAL (nlist * sizeof (GlyphListRec)); + if (!listsBase) + return BadAlloc; + } + buffer = (CARD8 *) (stuff + 1); + glyphs = glyphsBase; + lists = listsBase; + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + if (elt->len == 0xff) + { + if (buffer + sizeof (GlyphSet) < end) + { + memcpy(&gs, buffer, sizeof(GlyphSet)); + glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, + gs, + GlyphSetType, + SecurityReadAccess); + if (!glyphSet) + { + client->errorValue = gs; + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + return RenderErrBase + BadGlyphSet; + } + } + buffer += 4; + } + else + { + lists->xOff = elt->deltax; + lists->yOff = elt->deltay; + lists->format = glyphSet->format; + lists->len = 0; + n = elt->len; + while (n--) + { + if (buffer + size <= end) + { + switch (size) { + case 1: + glyph = *((CARD8 *)buffer); break; + case 2: + glyph = *((CARD16 *)buffer); break; + case 4: + default: + glyph = *((CARD32 *)buffer); break; + } + if ((*glyphs = FindGlyph (glyphSet, glyph))) + { + lists->len++; + glyphs++; + } + } + buffer += size; + } + space = size * elt->len; + if (space & 3) + buffer += 4 - (space & 3); + lists++; + } + } + if (buffer > end) + return BadLength; + + CompositeGlyphs (stuff->op, + pSrc, + pDst, + pFormat, + stuff->xSrc, + stuff->ySrc, + nlist, + listsBase, + glyphsBase); + + if (glyphsBase != glyphsLocal) + DEALLOCATE_LOCAL (glyphsBase); + if (listsBase != listsLocal) + DEALLOCATE_LOCAL (listsBase); + + return client->noClientException; +} + +static int +ProcRenderFillRectangles (ClientPtr client) +{ + PicturePtr pDst; + int things; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + if (!PictOpValid (stuff->op)) + { + client->errorValue = stuff->op; + return BadValue; + } + VERIFY_PICTURE (pDst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pDst->pDrawable) + return BadDrawable; + + things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); + if (things & 4) + return(BadLength); + things >>= 3; + + CompositeRects (stuff->op, + pDst, + &stuff->color, + things, + (xRectangle *) &stuff[1]); + + return client->noClientException; +} + +static void +SetBit (unsigned char *line, int x, int bit) +{ + unsigned char mask; + + if (screenInfo.bitmapBitOrder == LSBFirst) + mask = (1 << (x & 7)); + else + mask = (0x80 >> (x & 7)); + /* XXX assumes byte order is host byte order */ + line += (x >> 3); + if (bit) + *line |= mask; + else + *line &= ~mask; +} + +#define DITHER_DIM 2 + +static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { + { 1, 3, }, + { 4, 2, }, +}; + +#define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) + +static int +ProcRenderCreateCursor (ClientPtr client) +{ + REQUEST(xRenderCreateCursorReq); + PicturePtr pSrc; + ScreenPtr pScreen; + unsigned short width, height; + CARD32 *argbbits, *argb; + unsigned char *srcbits, *srcline; + unsigned char *mskbits, *mskline; + int stride; + int x, y; + int nbytes_mono; + CursorMetricRec cm; + CursorPtr pCursor; + CARD32 twocolor[3]; + int ncolor; + + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + VERIFY_PICTURE (pSrc, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + if (!pSrc->pDrawable) + return BadDrawable; + pScreen = pSrc->pDrawable->pScreen; + width = pSrc->pDrawable->width; + height = pSrc->pDrawable->height; + if ( stuff->x > width + || stuff->y > height ) + return (BadMatch); + argbbits = xalloc (width * height * sizeof (CARD32)); + if (!argbbits) + return (BadAlloc); + + stride = BitmapBytePad(width); + nbytes_mono = stride*height; + srcbits = (unsigned char *)xalloc(nbytes_mono); + if (!srcbits) + { + xfree (argbbits); + return (BadAlloc); + } + mskbits = (unsigned char *)xalloc(nbytes_mono); + if (!mskbits) + { + xfree(argbbits); + xfree(srcbits); + return (BadAlloc); + } + bzero ((char *) mskbits, nbytes_mono); + bzero ((char *) srcbits, nbytes_mono); + + if (pSrc->format == PICT_a8r8g8b8) + { + (*pScreen->GetImage) (pSrc->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + } + else + { + PixmapPtr pPixmap; + PicturePtr pPicture; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadImplementation); + } + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32); + if (!pPixmap) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return (BadAlloc); + } + pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, + client, &error); + if (!pPicture) + { + xfree (argbbits); + xfree (srcbits); + xfree (mskbits); + return error; + } + (*pScreen->DestroyPixmap) (pPixmap); + CompositePicture (PictOpSrc, + pSrc, 0, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + (*pScreen->GetImage) (pPicture->pDrawable, + 0, 0, width, height, ZPixmap, + 0xffffffff, (pointer) argbbits); + FreePicture (pPicture, 0); + } + /* + * Check whether the cursor can be directly supported by + * the core cursor code + */ + ncolor = 0; + argb = argbbits; + for (y = 0; ncolor <= 2 && y < height; y++) + { + for (x = 0; ncolor <= 2 && x < width; x++) + { + CARD32 p = *argb++; + CARD32 a = (p >> 24); + + if (a == 0) /* transparent */ + continue; + if (a == 0xff) /* opaque */ + { + int n; + for (n = 0; n < ncolor; n++) + if (p == twocolor[n]) + break; + if (n == ncolor) + twocolor[ncolor++] = p; + } + else + ncolor = 3; + } + } + + /* + * Convert argb image to two plane cursor + */ + srcline = srcbits; + mskline = mskbits; + argb = argbbits; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + CARD32 p = *argb++; + + if (ncolor <= 2) + { + CARD32 a = ((p >> 24)); + + SetBit (mskline, x, a != 0); + SetBit (srcline, x, a != 0 && p == twocolor[0]); + } + else + { + CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; + CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; + CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; + /* Set mask from dithered alpha value */ + SetBit(mskline, x, a > d); + /* Set src from dithered intensity value */ + SetBit(srcline, x, a > d && i <= d); + } + } + srcline += stride; + mskline += stride; + } + /* + * Dither to white and black if the cursor has more than two colors + */ + if (ncolor > 2) + { + twocolor[0] = 0xff000000; + twocolor[1] = 0xffffffff; + } + else + { + xfree (argbbits); + argbbits = 0; + } + +#define GetByte(p,s) (((p) >> (s)) & 0xff) +#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) + + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + pCursor = AllocCursorARGB (srcbits, mskbits, argbbits, &cm, + GetColor(twocolor[0], 16), + GetColor(twocolor[0], 8), + GetColor(twocolor[0], 0), + GetColor(twocolor[1], 16), + GetColor(twocolor[1], 8), + GetColor(twocolor[1], 0)); + if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return (client->noClientException); + return BadAlloc; +} + +static int +ProcRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + PicturePtr pPicture; + int result; + + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); + if (client->noClientException != Success) + return(client->noClientException); + else + return(result); +} + +static int +ProcRenderQueryFilters (ClientPtr client) +{ + REQUEST (xRenderQueryFiltersReq); + DrawablePtr pDrawable; + xRenderQueryFiltersReply *reply; + int nbytesName; + int nnames; + ScreenPtr pScreen; + PictureScreenPtr ps; + int i, j; + int len; + int total_bytes; + INT16 *aliases; + char *names; + + REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); + SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client, SecurityReadAccess); + + pScreen = pDrawable->pScreen; + nbytesName = 0; + nnames = 0; + ps = GetPictureScreenIfSet(pScreen); + if (ps) + { + for (i = 0; i < ps->nfilters; i++) + nbytesName += 1 + strlen (ps->filters[i].name); + for (i = 0; i < ps->nfilterAliases; i++) + nbytesName += 1 + strlen (ps->filterAliases[i].alias); + nnames = ps->nfilters + ps->nfilterAliases; + } + len = ((nnames + 1) >> 1) + ((nbytesName + 3) >> 2); + total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); + reply = (xRenderQueryFiltersReply *) xalloc (total_bytes); + if (!reply) + return BadAlloc; + aliases = (INT16 *) (reply + 1); + names = (char *) (aliases + ((nnames + 1) & ~1)); + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = len; + reply->numAliases = nnames; + reply->numFilters = nnames; + if (ps) + { + + /* fill in alias values */ + for (i = 0; i < ps->nfilters; i++) + aliases[i] = FilterAliasNone; + for (i = 0; i < ps->nfilterAliases; i++) + { + for (j = 0; j < ps->nfilters; j++) + if (ps->filterAliases[i].filter_id == ps->filters[j].id) + break; + if (j == ps->nfilters) + { + for (j = 0; j < ps->nfilterAliases; j++) + if (ps->filterAliases[i].filter_id == + ps->filterAliases[j].alias_id) + { + break; + } + if (j == ps->nfilterAliases) + j = FilterAliasNone; + else + j = j + ps->nfilters; + } + aliases[i + ps->nfilters] = j; + } + + /* fill in filter names */ + for (i = 0; i < ps->nfilters; i++) + { + j = strlen (ps->filters[i].name); + *names++ = j; + strncpy (names, ps->filters[i].name, j); + names += j; + } + + /* fill in filter alias names */ + for (i = 0; i < ps->nfilterAliases; i++) + { + j = strlen (ps->filterAliases[i].alias); + *names++ = j; + strncpy (names, ps->filterAliases[i].alias, j); + names += j; + } + } + + if (client->swapped) + { + register int n; + + for (i = 0; i < reply->numAliases; i++) + { + swaps (&aliases[i], n); + } + swaps(&reply->sequenceNumber, n); + swapl(&reply->length, n); + swapl(&reply->numAliases, n); + swapl(&reply->numFilters, n); + } + WriteToClient(client, total_bytes, (char *) reply); + xfree (reply); + + return(client->noClientException); +} + +static int +ProcRenderSetPictureFilter (ClientPtr client) +{ + REQUEST (xRenderSetPictureFilterReq); + PicturePtr pPicture; + int result; + xFixed *params; + int nparams; + char *name; + + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + name = (char *) (stuff + 1); + params = (xFixed *) (name + ((stuff->nbytes + 3) & ~3)); + nparams = ((xFixed *) stuff + client->req_len) - params; + result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); + return result; +} + +static int +ProcRenderCreateAnimCursor (ClientPtr client) +{ + REQUEST(xRenderCreateAnimCursorReq); + CursorPtr *cursors; + CARD32 *deltas; + CursorPtr pCursor; + int ncursor; + xAnimCursorElt *elt; + int i; + int ret; + + REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + if (client->req_len & 1) + return BadLength; + ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1; + cursors = xalloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); + if (!cursors) + return BadAlloc; + deltas = (CARD32 *) (cursors + ncursor); + elt = (xAnimCursorElt *) (stuff + 1); + for (i = 0; i < ncursor; i++) + { + cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor, + RT_CURSOR, SecurityReadAccess); + if (!cursors[i]) + { + xfree (cursors); + client->errorValue = elt->cursor; + return BadCursor; + } + deltas[i] = elt->delay; + elt++; + } + ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor); + xfree (cursors); + if (ret != Success) + return ret; + + if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) + return client->noClientException; + return BadAlloc; +} + +static int +ProcRenderAddTraps (ClientPtr client) +{ + int ntraps; + PicturePtr pPicture; + REQUEST(xRenderAddTrapsReq); + + REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq); + VERIFY_PICTURE (pPicture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + if (!pPicture->pDrawable) + return BadDrawable; + ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (ntraps % sizeof (xTrap)) + return BadLength; + ntraps /= sizeof (xTrap); + if (ntraps) + AddTraps (pPicture, + stuff->xOff, stuff->yOff, + ntraps, (xTrap *) &stuff[1]); + return client->noClientException; +} + +static int ProcRenderCreateSolidFill(ClientPtr client) +{ + PicturePtr pPicture; + int error = 0; + REQUEST(xRenderCreateSolidFillReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateLinearGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateLinearGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateRadialGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateRadialGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer, + stuff->inner_radius, stuff->outer_radius, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + +static int ProcRenderCreateConicalGradient (ClientPtr client) +{ + PicturePtr pPicture; + int len; + int error = 0; + xFixed *stops; + xRenderColor *colors; + REQUEST(xRenderCreateConicalGradientReq); + + REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); + + LEGAL_NEW_RESOURCE(stuff->pid, client); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + stops = (xFixed *)(stuff + 1); + colors = (xRenderColor *)(stops + stuff->nStops); + + pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle, + stuff->nStops, stops, colors, &error); + if (!pPicture) + return error; + if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) + return BadAlloc; + return Success; +} + + +static int +ProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*ProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +static int +SProcRenderQueryVersion (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryVersionReq); + + swaps(&stuff->length, n); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcRenderVector[stuff->renderReqType])(client); +} + +static int +SProcRenderQueryPictFormats (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictFormatsReq); + swaps(&stuff->length, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryPictIndexValues (ClientPtr client) +{ + register int n; + REQUEST(xRenderQueryPictIndexValuesReq); + swaps(&stuff->length, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryDithers (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreatePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreatePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swapl(&stuff->format, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderChangePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderChangePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->mask, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureClipRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureClipRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreePicture (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreePictureReq); + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderComposite (ClientPtr client) +{ + register int n; + REQUEST(xRenderCompositeReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->mask, n); + swapl(&stuff->dst, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xMask, n); + swaps(&stuff->yMask, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderScale (ClientPtr client) +{ + register int n; + REQUEST(xRenderScaleReq); + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->colorScale, n); + swapl(&stuff->alphaScale, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + swaps(&stuff->xDst, n); + swaps(&stuff->yDst, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTrapezoids (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrapezoidsReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderTrianglesReq); + + REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriStrip (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriStripReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderTriFan (ClientPtr client) +{ + register int n; + REQUEST(xRenderTriFanReq); + + REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); + swaps (&stuff->length, n); + swapl (&stuff->src, n); + swapl (&stuff->dst, n); + swapl (&stuff->maskFormat, n); + swaps (&stuff->xSrc, n); + swaps (&stuff->ySrc, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderColorTrapezoids (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderColorTriangles (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderTransform (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderCreateGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->format, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderReferenceGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderReferenceGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->gsid, n); + swapl(&stuff->existing, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFreeGlyphSet (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphSetReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphs (ClientPtr client) +{ + register int n; + register int i; + CARD32 *gids; + void *end; + xGlyphInfo *gi; + REQUEST(xRenderAddGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + swapl(&stuff->nglyphs, n); + if (stuff->nglyphs & 0xe0000000) + return BadLength; + end = (CARD8 *) stuff + (client->req_len << 2); + gids = (CARD32 *) (stuff + 1); + gi = (xGlyphInfo *) (gids + stuff->nglyphs); + if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) + return BadLength; + if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) + return BadLength; + for (i = 0; i < stuff->nglyphs; i++) + { + swapl (&gids[i], n); + swaps (&gi[i].width, n); + swaps (&gi[i].height, n); + swaps (&gi[i].x, n); + swaps (&gi[i].y, n); + swaps (&gi[i].xOff, n); + swaps (&gi[i].yOff, n); + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddGlyphsFromPicture (ClientPtr client) +{ + return BadImplementation; +} + +static int +SProcRenderFreeGlyphs (ClientPtr client) +{ + register int n; + REQUEST(xRenderFreeGlyphsReq); + swaps(&stuff->length, n); + swapl(&stuff->glyphset, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCompositeGlyphs (ClientPtr client) +{ + register int n; + xGlyphElt *elt; + CARD8 *buffer; + CARD8 *end; + int space; + int i; + int size; + + REQUEST(xRenderCompositeGlyphsReq); + + switch (stuff->renderReqType) { + default: size = 1; break; + case X_RenderCompositeGlyphs16: size = 2; break; + case X_RenderCompositeGlyphs32: size = 4; break; + } + + swaps(&stuff->length, n); + swapl(&stuff->src, n); + swapl(&stuff->dst, n); + swapl(&stuff->maskFormat, n); + swapl(&stuff->glyphset, n); + swaps(&stuff->xSrc, n); + swaps(&stuff->ySrc, n); + buffer = (CARD8 *) (stuff + 1); + end = (CARD8 *) stuff + (client->req_len << 2); + while (buffer + sizeof (xGlyphElt) < end) + { + elt = (xGlyphElt *) buffer; + buffer += sizeof (xGlyphElt); + + swaps (&elt->deltax, n); + swaps (&elt->deltay, n); + + i = elt->len; + if (i == 0xff) + { + swapl (buffer, n); + buffer += 4; + } + else + { + space = size * i; + switch (size) { + case 1: + buffer += i; + break; + case 2: + while (i--) + { + swaps (buffer, n); + buffer += 2; + } + break; + case 4: + while (i--) + { + swapl (buffer, n); + buffer += 4; + } + break; + } + if (space & 3) + buffer += 4 - (space & 3); + } + } + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderFillRectangles (ClientPtr client) +{ + register int n; + REQUEST(xRenderFillRectanglesReq); + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + swaps(&stuff->length, n); + swapl(&stuff->dst, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + swaps(&stuff->color.alpha, n); + SwapRestS(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateCursor (ClientPtr client) +{ + register int n; + REQUEST(xRenderCreateCursorReq); + REQUEST_SIZE_MATCH (xRenderCreateCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + swapl(&stuff->src, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureTransform (ClientPtr client) +{ + register int n; + REQUEST(xRenderSetPictureTransformReq); + REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swapl(&stuff->transform.matrix11, n); + swapl(&stuff->transform.matrix12, n); + swapl(&stuff->transform.matrix13, n); + swapl(&stuff->transform.matrix21, n); + swapl(&stuff->transform.matrix22, n); + swapl(&stuff->transform.matrix23, n); + swapl(&stuff->transform.matrix31, n); + swapl(&stuff->transform.matrix32, n); + swapl(&stuff->transform.matrix33, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderQueryFilters (ClientPtr client) +{ + register int n; + REQUEST (xRenderQueryFiltersReq); + REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); + + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderSetPictureFilter (ClientPtr client) +{ + register int n; + REQUEST (xRenderSetPictureFilterReq); + REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->nbytes, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateAnimCursor (ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateAnimCursorReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cid, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderAddTraps (ClientPtr client) +{ + register int n; + REQUEST (xRenderAddTrapsReq); + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + + swaps(&stuff->length, n); + swapl(&stuff->picture, n); + swaps(&stuff->xOff, n); + swaps(&stuff->yOff, n); + SwapRestL(stuff); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateSolidFill(ClientPtr client) +{ + register int n; + REQUEST (xRenderCreateSolidFillReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swaps(&stuff->color.alpha, n); + swaps(&stuff->color.red, n); + swaps(&stuff->color.green, n); + swaps(&stuff->color.blue, n); + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static void swapStops(void *stuff, int n) +{ + int i; + CARD32 *stops; + CARD16 *colors; + stops = (CARD32 *)(stuff); + for (i = 0; i < n; ++i) { + swapl(stops, n); + ++stops; + } + colors = (CARD16 *)(stops); + for (i = 0; i < 4*n; ++i) { + swaps(stops, n); + ++stops; + } +} + +static int +SProcRenderCreateLinearGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateLinearGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->p1.x, n); + swapl(&stuff->p1.y, n); + swapl(&stuff->p2.x, n); + swapl(&stuff->p2.y, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateRadialGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateRadialGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->inner.x, n); + swapl(&stuff->inner.y, n); + swapl(&stuff->outer.x, n); + swapl(&stuff->outer.y, n); + swapl(&stuff->inner_radius, n); + swapl(&stuff->outer_radius, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderCreateConicalGradient (ClientPtr client) +{ + register int n; + int len; + REQUEST (xRenderCreateConicalGradientReq); + REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq); + + swaps(&stuff->length, n); + swapl(&stuff->pid, n); + swapl(&stuff->center.x, n); + swapl(&stuff->center.y, n); + swapl(&stuff->angle, n); + swapl(&stuff->nStops, n); + + len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); + if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) + return BadLength; + + swapStops(stuff+1, stuff->nStops); + + return (*ProcRenderVector[stuff->renderReqType]) (client); +} + +static int +SProcRenderDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < RenderNumberRequests) + return (*SProcRenderVector[stuff->data]) (client); + else + return BadRequest; +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\ + pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\ + if (!pPicture) { \ + client->errorValue = pid; \ + return err; \ + } \ +} + +#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\ + if (pid == None) \ + pPicture = 0; \ + else { \ + VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \ + } \ +} \ + +int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); + +unsigned long XRT_PICTURE; + +static int +PanoramiXRenderCreatePicture (ClientPtr client) +{ + REQUEST(xRenderCreatePictureReq); + PanoramiXRes *refDraw, *newPict; + int result = Success, j; + + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); + if(!(refDraw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + newPict->type = XRT_PICTURE; + newPict->info[0].id = stuff->pid; + + if (refDraw->type == XRT_WINDOW && + stuff->drawable == WindowTable[0]->drawable.id) + { + newPict->u.pict.root = TRUE; + } + else + newPict->u.pict.root = FALSE; + + for(j = 1; j < PanoramiXNumScreens; j++) + newPict->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPict->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPict->info[0].id, XRT_PICTURE, newPict); + else + xfree(newPict); + + return (result); +} + +static int +PanoramiXRenderChangePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderChangePictureReq); + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureClipRectangles (ClientPtr client) +{ + REQUEST(xRenderSetPictureClipRectanglesReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureTransform (ClientPtr client) +{ + REQUEST(xRenderSetPictureTransformReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderSetPictureFilter (ClientPtr client) +{ + REQUEST(xRenderSetPictureFilterReq); + int result = Success, j; + PanoramiXRes *pict; + + REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client); + if(result != Success) break; + } + + return (result); +} + +static int +PanoramiXRenderFreePicture (ClientPtr client) +{ + PanoramiXRes *pict; + int result = Success, j; + REQUEST(xRenderFreePictureReq); + + REQUEST_SIZE_MATCH(xRenderFreePictureReq); + + client->errorValue = stuff->picture; + + VERIFY_XIN_PICTURE(pict, stuff->picture, client, SecurityDestroyAccess, + RenderErrBase + BadPicture); + + + FOR_NSCREENS_BACKWARD(j) { + stuff->picture = pict->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); + if(result != Success) break; + } + + /* Since ProcRenderFreePicture is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + +static int +PanoramiXRenderComposite (ClientPtr client) +{ + PanoramiXRes *src, *msk, *dst; + int result = Success, j; + xRenderCompositeReq orig; + REQUEST(xRenderCompositeReq); + + REQUEST_SIZE_MATCH(xRenderCompositeReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_ALPHA (msk, stuff->mask, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + orig = *stuff; + + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = orig.xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = orig.ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + stuff->xDst = orig.xDst - panoramiXdataPtr[j].x; + stuff->yDst = orig.yDst - panoramiXdataPtr[j].y; + } + if (msk) + { + stuff->mask = msk->info[j].id; + if (msk->u.pict.root) + { + stuff->xMask = orig.xMask - panoramiXdataPtr[j].x; + stuff->yMask = orig.yMask - panoramiXdataPtr[j].y; + } + } + result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); + if(result != Success) break; + } + + return result; +} + +static int +PanoramiXRenderCompositeGlyphs (ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderCompositeGlyphsReq); + xGlyphElt origElt, *elt; + INT16 xSrc, ySrc; + + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + + sizeof (xGlyphElt))) + { + elt = (xGlyphElt *) (stuff + 1); + origElt = *elt; + xSrc = stuff->xSrc; + ySrc = stuff->ySrc; + FOR_NSCREENS_FORWARD(j) { + stuff->src = src->info[j].id; + if (src->u.pict.root) + { + stuff->xSrc = xSrc - panoramiXdataPtr[j].x; + stuff->ySrc = ySrc - panoramiXdataPtr[j].y; + } + stuff->dst = dst->info[j].id; + if (dst->u.pict.root) + { + elt->deltax = origElt.deltax - panoramiXdataPtr[j].x; + elt->deltay = origElt.deltay - panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); + if(result != Success) break; + } + } + + return result; +} + +static int +PanoramiXRenderFillRectangles (ClientPtr client) +{ + PanoramiXRes *dst; + int result = Success, j; + REQUEST(xRenderFillRectanglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) + { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) (stuff + 1); + int i = extra_len / sizeof (xRectangle); + + while (i--) + { + rects->x -= x_off; + rects->y -= y_off; + rects++; + } + } + } + stuff->dst = dst->info[j].id; + result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTrapezoids(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrapezoidsReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTrapezoid *trap = (xTrapezoid *) (stuff + 1); + int i = extra_len / sizeof (xTrapezoid); + + while (i--) { + trap->top -= y_off; + trap->bottom -= y_off; + trap->left.p1.x -= x_off; + trap->left.p1.y -= y_off; + trap->left.p2.x -= x_off; + trap->left.p2.y -= y_off; + trap->right.p1.x -= x_off; + trap->right.p1.y -= y_off; + trap->right.p2.x -= x_off; + trap->right.p2.y -= y_off; + trap++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriangles(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTrianglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xTriangle *tri = (xTriangle *) (stuff + 1); + int i = extra_len / sizeof (xTriangle); + + while (i--) { + tri->p1.x -= x_off; + tri->p1.y -= y_off; + tri->p2.x -= x_off; + tri->p2.y -= y_off; + tri->p3.x -= x_off; + tri->p3.y -= y_off; + tri++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriStrip(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriStripReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriStripReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderTriFan(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderTriFanReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderTriFanReq); + + VERIFY_XIN_PICTURE (src, stuff->src, client, SecurityReadAccess, + RenderErrBase + BadPicture); + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPointFixed *fixed = (xPointFixed *) (stuff + 1); + int i = extra_len / sizeof (xPointFixed); + + while (i--) { + fixed->x -= x_off; + fixed->y -= y_off; + fixed++; + } + } + } + + stuff->src = src->info[j].id; + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +#if 0 /* Not implemented yet */ + +static int +PanoramiXRenderColorTrapezoids(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderColorTrapezoidsReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderColorTrapezoidsReq); + + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderColorTrapezoidsReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + ....; + } + } + + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderColorTrapezoids]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +static int +PanoramiXRenderColorTriangles(ClientPtr client) +{ + PanoramiXRes *src, *dst; + int result = Success, j; + REQUEST(xRenderColorTrianglesReq); + char *extra; + int extra_len; + + REQUEST_AT_LEAST_SIZE (xRenderColorTrianglesReq); + + VERIFY_XIN_PICTURE (dst, stuff->dst, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + + extra_len = (client->req_len << 2) - sizeof (xRenderColorTrianglesReq); + + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) { + memcpy (extra, stuff + 1, extra_len); + + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + if (dst->u.pict.root) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + ....; + } + } + + stuff->dst = dst->info[j].id; + result = + (*PanoramiXSaveRenderVector[X_RenderColorTriangles]) (client); + + if(result != Success) break; + } + + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +#endif + +static int +PanoramiXRenderAddTraps (ClientPtr client) +{ + PanoramiXRes *picture; + int result = Success, j; + REQUEST(xRenderAddTrapsReq); + char *extra; + int extra_len; + INT16 x_off, y_off; + + REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); + VERIFY_XIN_PICTURE (picture, stuff->picture, client, SecurityWriteAccess, + RenderErrBase + BadPicture); + extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); + if (extra_len && + (extra = (char *) ALLOCATE_LOCAL (extra_len))) + { + memcpy (extra, stuff + 1, extra_len); + x_off = stuff->xOff; + y_off = stuff->yOff; + FOR_NSCREENS_FORWARD(j) { + if (j) memcpy (stuff + 1, extra, extra_len); + stuff->picture = picture->info[j].id; + + if (picture->u.pict.root) + { + stuff->xOff = x_off + panoramiXdataPtr[j].x; + stuff->yOff = y_off + panoramiXdataPtr[j].y; + } + result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client); + if(result != Success) break; + } + DEALLOCATE_LOCAL(extra); + } + + return result; +} + +void +PanoramiXRenderInit (void) +{ + int i; + + XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource); + for (i = 0; i < RenderNumberRequests; i++) + PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; + ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; + ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform; + ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter; + ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; + ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; + ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; + ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; + ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; + + ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids; + ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles; + ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip; + ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan; + ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps; +} + +void +PanoramiXRenderReset (void) +{ + int i; + for (i = 0; i < RenderNumberRequests; i++) + ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; +} + +#endif /* PANORAMIX */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c new file mode 100644 index 000000000..9af5c4187 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c @@ -0,0 +1,1173 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $Xorg: resource.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/* $XdotOrg: xc/programs/Xserver/dix/resource.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */ +/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ +/* $XFree86: xc/programs/Xserver/dix/resource.c,v 3.13 2003/09/24 02:43:13 dawes Exp $ */ + +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include "dixfont.h" +#include "colormap.h" +#include "inputstr.h" +#include "dixevents.h" +#include "dixgrabs.h" +#include "cursor.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include + +#ifdef NXAGENT_SERVER + +#include "Agent.h" +#include "Font.h" +#include "Pixmaps.h" +#include "GCs.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#endif + +static void RebuildTable( + int /*client*/ +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +#ifdef XResExtension + +Atom * ResourceNames = NULL; + +void RegisterResourceName (RESTYPE type, char *name) +{ + ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); +} + +#endif + +RESTYPE +CreateNewResourceType(DeleteType deleteFunc) +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); + if(!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(ClientPtr client) +{ + register int i, j; + + if (client == serverClient) + { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + +#ifdef XResExtension + if(ResourceNames) + xfree(ResourceNames); + ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); + if(!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +AvailableID( + register int client, + register XID id, + register XID maxid, + register XID goodid) +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +void +GetXIDRange(int client, Bool server, XID *minp, XID *maxp) +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/** + * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +unsigned int +GetXIDList(ClientPtr pClient, unsigned count, XID *pids) +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +XID +FakeClientID(register int client) +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +#ifdef NXAGENT_SERVER + +int nxagentFindClientResource(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + int i; + + for (i = 0; i < clientTable[client].buckets; i++) + { + resources = clientTable[client].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == type && pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentFindClientResource: Found resource [%p] type [%lu] " + "for client [%d].\n", (void *) value, + pResource -> type, client); + #endif + + return 1; + } + } + } + + return 0; +} + +int nxagentSwitchResourceType(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + RESTYPE internalType = 0; + + int i; + + if (type == RT_PIXMAP) + { + internalType = RT_NX_PIXMAP; + } + else if (type == RT_GC) + { + internalType = RT_NX_GC; + } + else if (type == RT_FONT) + { + internalType = RT_NX_FONT; + } + else + { + return 0; + } + + if (client == serverClient -> index) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Requesting client is [%d]. Skipping the resource switch.\n", + client); + #endif + + return 0; + } + + for (i = 0; i < clientTable[serverClient -> index].buckets; i++) + { + resources = clientTable[serverClient -> index].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == internalType && + pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Changing resource [%p] type from [%lu] to " + "[%lu] for server client [%d].\n", (void *) value, + (unsigned long) pResource -> type, (unsigned long) type, serverClient -> index); + #endif + + FreeResource(pResource -> id, RT_NONE); + + return 1; + } + } + } + + return 0; +} + +#endif + +Bool +AddResource(XID id, RESTYPE type, pointer value) +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%lx, %lx, %lx), client=%d \n", + (unsigned long)id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + +#ifdef NXAGENT_SERVER + + nxagentSwitchResourceType(client, type, value); + + #ifdef TEST + fprintf(stderr, "AddResource: Adding resource for client [%d] type [%lu] value [%p] id [%lu].\n", + client, (unsigned long) type, (void *) value, (unsigned long) id); + #endif + +#endif + + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(int client) +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +void +FreeResource(XID id, RESTYPE skipDeleteFuncType) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + +#ifdef NXAGENT_SERVER + + #ifdef TEST + fprintf(stderr, "FreeResource: Freeing resource id [%lu].\n", (unsigned long) id); + #endif + +#endif + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + ErrorF("Freeing resource id=%lX which isn't there.\n", + (unsigned long)id); +} + + +void +FreeResourceByType(XID id, RESTYPE type, Bool skipFree) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +Bool +ChangeResourceValue (XID id, RESTYPE rtype, pointer value) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +void +FindClientResourcesByType( + ClientPtr client, + RESTYPE type, + FindResType func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + #ifdef NXAGENT_SERVER + register ResourcePtr **resptr; + #endif + + if (!client) + client = serverClient; + +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + #ifdef NXAGENT_SERVER + if (*resptr != resources) + goto RestartLoop; + #endif + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +void +FindAllClientResources( + ClientPtr client, + FindAllRes func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + #ifdef NXAGENT_SERVER + register ResourcePtr **resptr; + #endif + + if (!client) + client = serverClient; + +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + elements = *eltptr; + (*func)(this->value, this->id, this->type, cdata); + #ifdef NXAGENT_SERVER + if (*resptr != resources) + goto RestartLoop; + #endif + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } +} + + +pointer +LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata +){ + ResourcePtr *resources; + ResourcePtr this; + int i; + + #ifdef NXAGENT_SERVER + ResourcePtr **resptr; + Bool res; + #endif + + if (!client) + client = serverClient; + +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + + for (i = 0; i < clientTable[client->index].buckets; i++) { + for (this = resources[i]; this; this = this->next) { + if (!type || this->type == type) { + #ifdef NXAGENT_SERVER + res = (*func)(this->value, this->id, cdata); + + if (*resptr != resources) + goto RestartLoop; + + if (res) + return this->value; + #else + if((*func)(this->value, this->id, cdata)) + return this->value; + #endif + } + } + } + return NULL; +} + + +void +FreeClientNeverRetainResources(ClientPtr client) +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(ClientPtr client) +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].resources = NULL; + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +Bool +LegalNewID(XID id, register ClientPtr client) +{ + +#ifdef PANORAMIX + XID minid, maxid; + + if (!noPanoramiXExtension) { + minid = client->clientAsMask | (client->index ? + SERVER_BIT : SERVER_MINID); + maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; + if ((id >= minid) && (id <= maxid)) + return TRUE; + } +#endif /* PANORAMIX */ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +#ifdef XCSECURITY + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +pointer +SecurityLookupIDByType(ClientPtr client, XID id, RESTYPE rtype, Mask mode) +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert( (rtype & TypeMask) <= lastResourceType); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, rtype, mode, retval); + return retval; +} + + +pointer +SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode) +{ + int cid; + register ResourcePtr res = NULL; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert (classes >= lastResourceClass); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, res->type, mode, retval); + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +pointer +LookupIDByType(XID id, RESTYPE rtype) +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +pointer +LookupIDByClass(XID id, RESTYPE classes) +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +/* + * LookupIDByType returns the object with the given id and type, else NULL. + */ +pointer +LookupIDByType(XID id, RESTYPE rtype) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + return res->value; + } + return (pointer)NULL; +} + +/* + * LookupIDByClass returns the object with the given id and any one of the + * given classes, else NULL. + */ +pointer +LookupIDByClass(XID id, RESTYPE classes) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + return res->value; + } + return (pointer)NULL; +} + +#endif /* XCSECURITY */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.NX.original new file mode 100644 index 000000000..9af5c4187 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.NX.original @@ -0,0 +1,1173 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $Xorg: resource.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/* $XdotOrg: xc/programs/Xserver/dix/resource.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */ +/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ +/* $XFree86: xc/programs/Xserver/dix/resource.c,v 3.13 2003/09/24 02:43:13 dawes Exp $ */ + +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include "dixfont.h" +#include "colormap.h" +#include "inputstr.h" +#include "dixevents.h" +#include "dixgrabs.h" +#include "cursor.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include + +#ifdef NXAGENT_SERVER + +#include "Agent.h" +#include "Font.h" +#include "Pixmaps.h" +#include "GCs.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#endif + +static void RebuildTable( + int /*client*/ +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +#ifdef XResExtension + +Atom * ResourceNames = NULL; + +void RegisterResourceName (RESTYPE type, char *name) +{ + ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); +} + +#endif + +RESTYPE +CreateNewResourceType(DeleteType deleteFunc) +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); + if(!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(ClientPtr client) +{ + register int i, j; + + if (client == serverClient) + { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + +#ifdef XResExtension + if(ResourceNames) + xfree(ResourceNames); + ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); + if(!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +AvailableID( + register int client, + register XID id, + register XID maxid, + register XID goodid) +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +void +GetXIDRange(int client, Bool server, XID *minp, XID *maxp) +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/** + * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +unsigned int +GetXIDList(ClientPtr pClient, unsigned count, XID *pids) +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +XID +FakeClientID(register int client) +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +#ifdef NXAGENT_SERVER + +int nxagentFindClientResource(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + int i; + + for (i = 0; i < clientTable[client].buckets; i++) + { + resources = clientTable[client].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == type && pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentFindClientResource: Found resource [%p] type [%lu] " + "for client [%d].\n", (void *) value, + pResource -> type, client); + #endif + + return 1; + } + } + } + + return 0; +} + +int nxagentSwitchResourceType(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + RESTYPE internalType = 0; + + int i; + + if (type == RT_PIXMAP) + { + internalType = RT_NX_PIXMAP; + } + else if (type == RT_GC) + { + internalType = RT_NX_GC; + } + else if (type == RT_FONT) + { + internalType = RT_NX_FONT; + } + else + { + return 0; + } + + if (client == serverClient -> index) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Requesting client is [%d]. Skipping the resource switch.\n", + client); + #endif + + return 0; + } + + for (i = 0; i < clientTable[serverClient -> index].buckets; i++) + { + resources = clientTable[serverClient -> index].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == internalType && + pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Changing resource [%p] type from [%lu] to " + "[%lu] for server client [%d].\n", (void *) value, + (unsigned long) pResource -> type, (unsigned long) type, serverClient -> index); + #endif + + FreeResource(pResource -> id, RT_NONE); + + return 1; + } + } + } + + return 0; +} + +#endif + +Bool +AddResource(XID id, RESTYPE type, pointer value) +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%lx, %lx, %lx), client=%d \n", + (unsigned long)id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + +#ifdef NXAGENT_SERVER + + nxagentSwitchResourceType(client, type, value); + + #ifdef TEST + fprintf(stderr, "AddResource: Adding resource for client [%d] type [%lu] value [%p] id [%lu].\n", + client, (unsigned long) type, (void *) value, (unsigned long) id); + #endif + +#endif + + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(int client) +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +void +FreeResource(XID id, RESTYPE skipDeleteFuncType) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + +#ifdef NXAGENT_SERVER + + #ifdef TEST + fprintf(stderr, "FreeResource: Freeing resource id [%lu].\n", (unsigned long) id); + #endif + +#endif + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + ErrorF("Freeing resource id=%lX which isn't there.\n", + (unsigned long)id); +} + + +void +FreeResourceByType(XID id, RESTYPE type, Bool skipFree) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +Bool +ChangeResourceValue (XID id, RESTYPE rtype, pointer value) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +void +FindClientResourcesByType( + ClientPtr client, + RESTYPE type, + FindResType func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + #ifdef NXAGENT_SERVER + register ResourcePtr **resptr; + #endif + + if (!client) + client = serverClient; + +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + #ifdef NXAGENT_SERVER + if (*resptr != resources) + goto RestartLoop; + #endif + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +void +FindAllClientResources( + ClientPtr client, + FindAllRes func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + #ifdef NXAGENT_SERVER + register ResourcePtr **resptr; + #endif + + if (!client) + client = serverClient; + +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + elements = *eltptr; + (*func)(this->value, this->id, this->type, cdata); + #ifdef NXAGENT_SERVER + if (*resptr != resources) + goto RestartLoop; + #endif + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } +} + + +pointer +LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata +){ + ResourcePtr *resources; + ResourcePtr this; + int i; + + #ifdef NXAGENT_SERVER + ResourcePtr **resptr; + Bool res; + #endif + + if (!client) + client = serverClient; + +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + + for (i = 0; i < clientTable[client->index].buckets; i++) { + for (this = resources[i]; this; this = this->next) { + if (!type || this->type == type) { + #ifdef NXAGENT_SERVER + res = (*func)(this->value, this->id, cdata); + + if (*resptr != resources) + goto RestartLoop; + + if (res) + return this->value; + #else + if((*func)(this->value, this->id, cdata)) + return this->value; + #endif + } + } + } + return NULL; +} + + +void +FreeClientNeverRetainResources(ClientPtr client) +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(ClientPtr client) +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].resources = NULL; + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +Bool +LegalNewID(XID id, register ClientPtr client) +{ + +#ifdef PANORAMIX + XID minid, maxid; + + if (!noPanoramiXExtension) { + minid = client->clientAsMask | (client->index ? + SERVER_BIT : SERVER_MINID); + maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; + if ((id >= minid) && (id <= maxid)) + return TRUE; + } +#endif /* PANORAMIX */ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +#ifdef XCSECURITY + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +pointer +SecurityLookupIDByType(ClientPtr client, XID id, RESTYPE rtype, Mask mode) +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert( (rtype & TypeMask) <= lastResourceType); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, rtype, mode, retval); + return retval; +} + + +pointer +SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode) +{ + int cid; + register ResourcePtr res = NULL; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert (classes >= lastResourceClass); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, res->type, mode, retval); + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +pointer +LookupIDByType(XID id, RESTYPE rtype) +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +pointer +LookupIDByClass(XID id, RESTYPE classes) +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +/* + * LookupIDByType returns the object with the given id and type, else NULL. + */ +pointer +LookupIDByType(XID id, RESTYPE rtype) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + return res->value; + } + return (pointer)NULL; +} + +/* + * LookupIDByClass returns the object with the given id and any one of the + * given classes, else NULL. + */ +pointer +LookupIDByClass(XID id, RESTYPE classes) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + return res->value; + } + return (pointer)NULL; +} + +#endif /* XCSECURITY */ + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original new file mode 100644 index 000000000..e12bc7b67 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original @@ -0,0 +1,954 @@ +/************************************************************ + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $Xorg: resource.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ +/* $XdotOrg: xc/programs/Xserver/dix/resource.c,v 1.8 2005/07/03 08:53:38 daniels Exp $ */ +/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */ + +/* Routines to manage various kinds of resources: + * + * CreateNewResourceType, CreateNewResourceClass, InitClientResources, + * FakeClientID, AddResource, FreeResource, FreeClientResources, + * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange + */ + +/* + * A resource ID is a 32 bit quantity, the upper 2 bits of which are + * off-limits for client-visible resources. The next 8 bits are + * used as client ID, and the low 22 bits come from the client. + * A resource ID is "hashed" by extracting and xoring subfields + * (varying with the size of the hash table). + * + * It is sometimes necessary for the server to create an ID that looks + * like it belongs to a client. This ID, however, must not be one + * the client actually can create, or we have the potential for conflict. + * The 31st bit of the ID is reserved for the server's use for this + * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to + * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a + * resource "owned" by the client. + */ +/* $XFree86: xc/programs/Xserver/dix/resource.c,v 3.13 2003/09/24 02:43:13 dawes Exp $ */ + +#define NEED_EVENTS +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "misc.h" +#include "os.h" +#include "resource.h" +#include "dixstruct.h" +#include "opaque.h" +#include "windowstr.h" +#include "dixfont.h" +#include "colormap.h" +#include "inputstr.h" +#include "dixevents.h" +#include "dixgrabs.h" +#include "cursor.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include + +static void RebuildTable( + int /*client*/ +); + +#define SERVER_MINID 32 + +#define INITBUCKETS 64 +#define INITHASHSIZE 6 +#define MAXHASHSIZE 11 + +typedef struct _Resource { + struct _Resource *next; + XID id; + RESTYPE type; + pointer value; +} ResourceRec, *ResourcePtr; +#define NullResource ((ResourcePtr)NULL) + +typedef struct _ClientResource { + ResourcePtr *resources; + int elements; + int buckets; + int hashsize; /* log(2)(buckets) */ + XID fakeID; + XID endFakeID; + XID expectID; +} ClientResourceRec; + +RESTYPE lastResourceType; +static RESTYPE lastResourceClass; +RESTYPE TypeMask; + +static DeleteType *DeleteFuncs = (DeleteType *)NULL; + +#ifdef XResExtension + +Atom * ResourceNames = NULL; + +void RegisterResourceName (RESTYPE type, char *name) +{ + ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE); +} + +#endif + +RESTYPE +CreateNewResourceType(DeleteType deleteFunc) +{ + RESTYPE next = lastResourceType + 1; + DeleteType *funcs; + + if (next & lastResourceClass) + return 0; + funcs = (DeleteType *)xrealloc(DeleteFuncs, + (next + 1) * sizeof(DeleteType)); + if (!funcs) + return 0; + +#ifdef XResExtension + { + Atom *newnames; + newnames = xrealloc(ResourceNames, (next + 1) * sizeof(Atom)); + if(!newnames) + return 0; + ResourceNames = newnames; + ResourceNames[next] = 0; + } +#endif + + lastResourceType = next; + DeleteFuncs = funcs; + DeleteFuncs[next] = deleteFunc; + return next; +} + +RESTYPE +CreateNewResourceClass() +{ + RESTYPE next = lastResourceClass >> 1; + + if (next & lastResourceType) + return 0; + lastResourceClass = next; + TypeMask = next - 1; + return next; +} + +ClientResourceRec clientTable[MAXCLIENTS]; + +/***************** + * InitClientResources + * When a new client is created, call this to allocate space + * in resource table + *****************/ + +Bool +InitClientResources(ClientPtr client) +{ + register int i, j; + + if (client == serverClient) + { + lastResourceType = RT_LASTPREDEF; + lastResourceClass = RC_LASTPREDEF; + TypeMask = RC_LASTPREDEF - 1; + if (DeleteFuncs) + xfree(DeleteFuncs); + DeleteFuncs = (DeleteType *)xalloc((lastResourceType + 1) * + sizeof(DeleteType)); + if (!DeleteFuncs) + return FALSE; + DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA; + DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow; + DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap; + DeleteFuncs[RT_GC & TypeMask] = FreeGC; + DeleteFuncs[RT_FONT & TypeMask] = CloseFont; + DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor; + DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap; + DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels; + DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone; + DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab; + +#ifdef XResExtension + if(ResourceNames) + xfree(ResourceNames); + ResourceNames = xalloc((lastResourceType + 1) * sizeof(Atom)); + if(!ResourceNames) + return FALSE; +#endif + } + clientTable[i = client->index].resources = + (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr)); + if (!clientTable[i].resources) + return FALSE; + clientTable[i].buckets = INITBUCKETS; + clientTable[i].elements = 0; + clientTable[i].hashsize = INITHASHSIZE; + /* Many IDs allocated from the server client are visible to clients, + * so we don't use the SERVER_BIT for them, but we have to start + * past the magic value constants used in the protocol. For normal + * clients, we can start from zero, with SERVER_BIT set. + */ + clientTable[i].fakeID = client->clientAsMask | + (client->index ? SERVER_BIT : SERVER_MINID); + clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; + clientTable[i].expectID = client->clientAsMask; + for (j=0; j>6) ^ (id>>12)))); + case 7: + return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); + case 8: + return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); + case 9: + return ((int)(0x1FF & (id ^ (id>>9)))); + case 10: + return ((int)(0x3FF & (id ^ (id>>10)))); + case 11: + return ((int)(0x7FF & (id ^ (id>>11)))); + } + return -1; +} + +static XID +AvailableID( + register int client, + register XID id, + register XID maxid, + register XID goodid) +{ + register ResourcePtr res; + + if ((goodid >= id) && (goodid <= maxid)) + return goodid; + for (; id <= maxid; id++) + { + res = clientTable[client].resources[Hash(client, id)]; + while (res && (res->id != id)) + res = res->next; + if (!res) + return id; + } + return 0; +} + +void +GetXIDRange(int client, Bool server, XID *minp, XID *maxp) +{ + register XID id, maxid; + register ResourcePtr *resp; + register ResourcePtr res; + register int i; + XID goodid; + + id = (Mask)client << CLIENTOFFSET; + if (server) + id |= client ? SERVER_BIT : SERVER_MINID; + maxid = id | RESOURCE_ID_MASK; + goodid = 0; + for (resp = clientTable[client].resources, i = clientTable[client].buckets; + --i >= 0;) + { + for (res = *resp++; res; res = res->next) + { + if ((res->id < id) || (res->id > maxid)) + continue; + if (((res->id - id) >= (maxid - res->id)) ? + (goodid = AvailableID(client, id, res->id - 1, goodid)) : + !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) + maxid = res->id - 1; + else + id = res->id + 1; + } + } + if (id > maxid) + id = maxid = 0; + *minp = id; + *maxp = maxid; +} + +/** + * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. + * This function tries to find count unused XIDs for the given client. It + * puts the IDs in the array pids and returns the number found, which should + * almost always be the number requested. + * + * The circumstances that lead to a call to this function are very rare. + * Xlib must run out of IDs while trying to generate a request that wants + * multiple ID's, like the Multi-buffering CreateImageBuffers request. + * + * No rocket science in the implementation; just iterate over all + * possible IDs for the given client and pick the first count IDs + * that aren't in use. A more efficient algorithm could probably be + * invented, but this will be used so rarely that this should suffice. + */ + +unsigned int +GetXIDList(ClientPtr pClient, unsigned count, XID *pids) +{ + unsigned int found = 0; + XID id = pClient->clientAsMask; + XID maxid; + + maxid = id | RESOURCE_ID_MASK; + while ( (found < count) && (id <= maxid) ) + { + if (!LookupIDByClass(id, RC_ANY)) + { + pids[found++] = id; + } + id++; + } + return found; +} + +/* + * Return the next usable fake client ID. + * + * Normally this is just the next one in line, but if we've used the last + * in the range, we need to find a new range of safe IDs to avoid + * over-running another client. + */ + +XID +FakeClientID(register int client) +{ + XID id, maxid; + + id = clientTable[client].fakeID++; + if (id != clientTable[client].endFakeID) + return id; + GetXIDRange(client, TRUE, &id, &maxid); + if (!id) { + if (!client) + FatalError("FakeClientID: server internal ids exhausted\n"); + MarkClientException(clients[client]); + id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); + maxid = id | RESOURCE_ID_MASK; + } + clientTable[client].fakeID = id + 1; + clientTable[client].endFakeID = maxid + 1; + return id; +} + +Bool +AddResource(XID id, RESTYPE type, pointer value) +{ + int client; + register ClientResourceRec *rrec; + register ResourcePtr res, *head; + + client = CLIENT_ID(id); + rrec = &clientTable[client]; + if (!rrec->buckets) + { + ErrorF("AddResource(%lx, %lx, %lx), client=%d \n", + (unsigned long)id, type, (unsigned long)value, client); + FatalError("client not in use\n"); + } + if ((rrec->elements >= 4*rrec->buckets) && + (rrec->hashsize < MAXHASHSIZE)) + RebuildTable(client); + head = &rrec->resources[Hash(client, id)]; + res = (ResourcePtr)xalloc(sizeof(ResourceRec)); + if (!res) + { + (*DeleteFuncs[type & TypeMask])(value, id); + return FALSE; + } + res->next = *head; + res->id = id; + res->type = type; + res->value = value; + *head = res; + rrec->elements++; + if (!(id & SERVER_BIT) && (id >= rrec->expectID)) + rrec->expectID = id + 1; + return TRUE; +} + +static void +RebuildTable(int client) +{ + register int j; + register ResourcePtr res, next; + ResourcePtr **tails, *resources; + register ResourcePtr **tptr, *rptr; + + /* + * For now, preserve insertion order, since some ddx layers depend + * on resources being free in the opposite order they are added. + */ + + j = 2 * clientTable[client].buckets; + tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *)); + if (!tails) + return; + resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr)); + if (!resources) + { + DEALLOCATE_LOCAL(tails); + return; + } + for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) + { + *rptr = NullResource; + *tptr = rptr; + } + clientTable[client].hashsize++; + for (j = clientTable[client].buckets, + rptr = clientTable[client].resources; + --j >= 0; + rptr++) + { + for (res = *rptr; res; res = next) + { + next = res->next; + res->next = NullResource; + tptr = &tails[Hash(client, res->id)]; + **tptr = res; + *tptr = &res->next; + } + } + DEALLOCATE_LOCAL(tails); + clientTable[client].buckets *= 2; + xfree(clientTable[client].resources); + clientTable[client].resources = resources; +} + +void +FreeResource(XID id, RESTYPE skipDeleteFuncType) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + register int *eltptr; + int elements; + Bool gotOne = FALSE; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id) + { + RESTYPE rtype = res->type; + *prev = res->next; + elements = --*eltptr; + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + if (rtype != skipDeleteFuncType) + (*DeleteFuncs[rtype & TypeMask])(res->value, res->id); + xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ + gotOne = TRUE; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } + if (!gotOne) + ErrorF("Freeing resource id=%lX which isn't there.\n", + (unsigned long)id); +} + + +void +FreeResourceByType(XID id, RESTYPE type, Bool skipFree) +{ + int cid; + register ResourcePtr res; + register ResourcePtr *prev, *head; + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + head = &clientTable[cid].resources[Hash(cid, id)]; + + prev = head; + while ( (res = *prev) ) + { + if (res->id == id && res->type == type) + { + *prev = res->next; + if (type & RC_CACHED) + FlushClientCaches(res->id); + if (!skipFree) + (*DeleteFuncs[type & TypeMask])(res->value, res->id); + xfree(res); + break; + } + else + prev = &res->next; + } + if(clients[cid] && (id == clients[cid]->lastDrawableID)) + { + clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0]; + clients[cid]->lastDrawableID = WindowTable[0]->drawable.id; + } + } +} + +/* + * Change the value associated with a resource id. Caller + * is responsible for "doing the right thing" with the old + * data + */ + +Bool +ChangeResourceValue (XID id, RESTYPE rtype, pointer value) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + if (rtype & RC_CACHED) + FlushClientCaches(res->id); + res->value = value; + return TRUE; + } + } + return FALSE; +} + +/* Note: if func adds or deletes resources, then func can get called + * more than once for some resources. If func adds new resources, + * func might or might not get called for them. func cannot both + * add and delete an equal number of resources! + */ + +void +FindClientResourcesByType( + ClientPtr client, + RESTYPE type, + FindResType func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + if (!type || this->type == type) { + elements = *eltptr; + (*func)(this->value, this->id, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } + } +} + +void +FindAllClientResources( + ClientPtr client, + FindAllRes func, + pointer cdata +){ + register ResourcePtr *resources; + register ResourcePtr this, next; + int i, elements; + register int *eltptr; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + eltptr = &clientTable[client->index].elements; + for (i = 0; i < clientTable[client->index].buckets; i++) + { + for (this = resources[i]; this; this = next) + { + next = this->next; + elements = *eltptr; + (*func)(this->value, this->id, this->type, cdata); + if (*eltptr != elements) + next = resources[i]; /* start over */ + } + } +} + + +pointer +LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata +){ + ResourcePtr *resources; + ResourcePtr this; + int i; + + if (!client) + client = serverClient; + + resources = clientTable[client->index].resources; + for (i = 0; i < clientTable[client->index].buckets; i++) { + for (this = resources[i]; this; this = this->next) { + if (!type || this->type == type) { + if((*func)(this->value, this->id, cdata)) + return this->value; + } + } + } + return NULL; +} + + +void +FreeClientNeverRetainResources(ClientPtr client) +{ + ResourcePtr *resources; + ResourcePtr this; + ResourcePtr *prev; + int j; + + if (!client) + return; + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + prev = &resources[j]; + while ( (this = *prev) ) + { + RESTYPE rtype = this->type; + if (rtype & RC_NEVERRETAIN) + { + *prev = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + else + prev = &this->next; + } + } +} + +void +FreeClientResources(ClientPtr client) +{ + register ResourcePtr *resources; + register ResourcePtr this; + int j; + + /* This routine shouldn't be called with a null client, but just in + case ... */ + + if (!client) + return; + + HandleSaveSet(client); + + resources = clientTable[client->index].resources; + for (j=0; j < clientTable[client->index].buckets; j++) + { + /* It may seem silly to update the head of this resource list as + we delete the members, since the entire list will be deleted any way, + but there are some resource deletion functions "FreeClientPixels" for + one which do a LookupID on another resource id (a Colormap id in this + case), so the resource list must be kept valid up to the point that + it is deleted, so every time we delete a resource, we must update the + head, just like in FreeResource. I hope that this doesn't slow down + mass deletion appreciably. PRH */ + + ResourcePtr *head; + + head = &resources[j]; + + for (this = *head; this; this = *head) + { + RESTYPE rtype = this->type; + *head = this->next; + if (rtype & RC_CACHED) + FlushClientCaches(this->id); + (*DeleteFuncs[rtype & TypeMask])(this->value, this->id); + xfree(this); + } + } + xfree(clientTable[client->index].resources); + clientTable[client->index].resources = NULL; + clientTable[client->index].buckets = 0; +} + +void +FreeAllResources() +{ + int i; + + for (i = currentMaxClients; --i >= 0; ) + { + if (clientTable[i].buckets) + FreeClientResources(clients[i]); + } +} + +Bool +LegalNewID(XID id, register ClientPtr client) +{ + +#ifdef PANORAMIX + XID minid, maxid; + + if (!noPanoramiXExtension) { + minid = client->clientAsMask | (client->index ? + SERVER_BIT : SERVER_MINID); + maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; + if ((id >= minid) && (id <= maxid)) + return TRUE; + } +#endif /* PANORAMIX */ + return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && + ((clientTable[client->index].expectID <= id) || + !LookupIDByClass(id, RC_ANY))); +} + +#ifdef XCSECURITY + +/* SecurityLookupIDByType and SecurityLookupIDByClass: + * These are the heart of the resource ID security system. They take + * two additional arguments compared to the old LookupID functions: + * the client doing the lookup, and the access mode (see resource.h). + * The resource is returned if it exists and the client is allowed access, + * else NULL is returned. + */ + +pointer +SecurityLookupIDByType(ClientPtr client, XID id, RESTYPE rtype, Mask mode) +{ + int cid; + register ResourcePtr res; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert( (rtype & TypeMask) <= lastResourceType); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, rtype, mode, retval); + return retval; +} + + +pointer +SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode) +{ + int cid; + register ResourcePtr res = NULL; + pointer retval = NULL; + + assert(client == NullClient || + (client->index <= currentMaxClients && clients[client->index] == client)); + assert (classes >= lastResourceClass); + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + { + retval = res->value; + break; + } + } + if (retval && client && client->CheckAccess) + retval = (* client->CheckAccess)(client, id, res->type, mode, retval); + return retval; +} + +/* We can't replace the LookupIDByType and LookupIDByClass functions with + * macros because of compatibility with loadable servers. + */ + +pointer +LookupIDByType(XID id, RESTYPE rtype) +{ + return SecurityLookupIDByType(NullClient, id, rtype, + SecurityUnknownAccess); +} + +pointer +LookupIDByClass(XID id, RESTYPE classes) +{ + return SecurityLookupIDByClass(NullClient, id, classes, + SecurityUnknownAccess); +} + +#else /* not XCSECURITY */ + +/* + * LookupIDByType returns the object with the given id and type, else NULL. + */ +pointer +LookupIDByType(XID id, RESTYPE rtype) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type == rtype)) + return res->value; + } + return (pointer)NULL; +} + +/* + * LookupIDByClass returns the object with the given id and any one of the + * given classes, else NULL. + */ +pointer +LookupIDByClass(XID id, RESTYPE classes) +{ + int cid; + register ResourcePtr res; + + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && + clientTable[cid].buckets) + { + res = clientTable[cid].resources[Hash(cid, id)]; + + for (; res; res = res->next) + if ((res->id == id) && (res->type & classes)) + return res->value; + } + return (pointer)NULL; +} + +#endif /* XCSECURITY */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c new file mode 100644 index 000000000..3aecaf229 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c @@ -0,0 +1,1455 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.41 2003/12/17 23:28:56 alanh Exp $ */ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#define SHM + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#ifndef Lynx +#include +#include +#else +#include +#include +#endif +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include +#include +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "modinit.h" + +#include "Trap.h" +#include "Agent.h" +#include "Drawable.h" +#include "Pixmaps.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#ifdef TEST +#include "Literals.h" +#endif + +extern void fbGetImage(DrawablePtr pDrw, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + +extern void fbPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *pImage); + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( + pointer /* value */, + XID /* shmseg */ + ); +static void ShmResetProc( + ExtensionEntry * /* extEntry */ + ); +static void SShmCompletionEvent( + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +#ifdef PIXPRIV +static int shmPixmapPrivate; +#endif +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall() +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + + if (shmid != -1) + { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + else + { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + +void +ShmExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + if (nxagentOption(SharedMemory) == False) + { + return; + } + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + sharedPixmaps = nxagentOption(SharedPixmaps); + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + { + #ifdef TEST + fprintf(stderr, "ShmExtensionInit: Registering shmFuncs as miFuncs.\n"); + #endif + shmFuncs[i] = &miFuncs; + } + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; + if (sharedPixmaps) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } +#ifdef PIXPRIV + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } +#endif + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs( + ScreenPtr pScreen, + ShmFuncsPtr funcs) +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat( + ScreenPtr pScreen, + int format) +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; +#ifdef PIXPRIV + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; +#else + char *base = (char *) pPixmap->devPrivate.ptr; + + if (base != (pointer) (pPixmap + 1)) + { + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) + { + if (shmdesc->addr <= base && base <= shmdesc->addr + shmdesc->size) + break; + } + } + else + shmdesc = 0; +#endif + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + #ifdef TEST + fprintf(stderr, "ShmRegisterFbFuncs: Registering shmFuncs as fbFuncs.\n"); + #endif + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + xfree(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + nxagentShmTrap = 0; + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + { + nxagentShmTrap = 1; + return; + } + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + nxagentShmTrap = 1; + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); + nxagentShmTrap = 1; +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + int length; + char *newdata; + extern int nxagentImageLength(int, int, int, int, int); + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Called with drawable at [%p] GC at [%p] data at [%p].\n", + (void *) dst, (void *) pGC, (void *) data); + #endif + + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + + /* + * We updated the internal framebuffer, + * now we want to go on the real X. + */ + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Realizing the PutImage with depth [%d] " + " format [%d] w [%d] h [%d] sx [%d] sy [%d] sw [%d] " + " sh [%d] dx [%d].\n", depth, format, w, h, + sx, sy, sw, sh, dx); + #endif + + length = nxagentImageLength(sw, sh, format, 0, depth); + + if ((newdata = xalloc(length)) != NULL) + { + fbGetImage((DrawablePtr) pPixmap, sx, sy, sw, sh, format, AllPlanes, newdata); + (*pGC->ops->PutImage)(dst, pGC, depth, dx, dy, sw, sh, 0, format, newdata); + + xfree(newdata); + } + else + { + #ifdef WARNING + fprintf(stderr, "fbShmPutImage: WARNING! Data allocation failed.\n"); + #endif + } + + FreeScratchPixmapHeader(pPixmap); + } + else + { + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Calling miShmPutImage().\n"); + #endif + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); + } +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(register ClientPtr client) +{ + int j, result = 0, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != client->noClientException) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + + if (client->swapped) { + register int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static int +ProcPanoramiXShmCreatePixmap( + register ClientPtr client) +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + PanoramiXRes *newPix; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = (client->noClientException); + + FOR_NSCREENS(j) { + pScreen = screenInfo.screens[j]; + + pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + xfree(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Format [%d] srcX [%d] srcY [%d], " + "totalWidth [%d] totalHeight [%d]\n", stuff->format, stuff->srcX, + stuff->srcY, stuff->totalWidth, stuff->totalHeight); + #endif + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Calling (*shmFuncs[pDraw->pScreen->myNum]->PutImage)().\n"); + #endif + + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + stuff->offset); + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else + { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + nxagentShmPixmapTrap = 1; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, width, height, depth); + + if (!pPixmap) + { + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + #ifdef TEST + fprintf(stderr,"fbShmCreatePixmap: Width [%d] Height [%d] Depth [%d]\n", width, height, depth); + #endif + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) + { + #ifdef WARNING + fprintf(stderr,"fbShmCreatePixmap: Return Null Pixmap.\n"); + #endif + + (*pScreen->DestroyPixmap)(pPixmap); + + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + nxagentShmPixmapTrap = 0; + + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return(client->noClientException); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + + if (stuff->data <= X_ShmCreatePixmap) + { + fprintf(stderr, "ProcShmDispatch: Request [%s] OPCODE#%d.\n", + nxagentShmRequestLiteral[stuff->data], stuff->data); + } + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + { + result = ProcPanoramiXShmPutImage(client); + + nxagentShmTrap = 0; + + return result; + } +#endif + + result = ProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Returning from ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + + result = SProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Returning from SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.NX.original new file mode 100644 index 000000000..3aecaf229 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.NX.original @@ -0,0 +1,1455 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.41 2003/12/17 23:28:56 alanh Exp $ */ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#define SHM + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#ifndef Lynx +#include +#include +#else +#include +#include +#endif +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include +#include +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "modinit.h" + +#include "Trap.h" +#include "Agent.h" +#include "Drawable.h" +#include "Pixmaps.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#ifdef TEST +#include "Literals.h" +#endif + +extern void fbGetImage(DrawablePtr pDrw, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d); + +extern void fbPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *pImage); + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( + pointer /* value */, + XID /* shmseg */ + ); +static void ShmResetProc( + ExtensionEntry * /* extEntry */ + ); +static void SShmCompletionEvent( + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +#ifdef PIXPRIV +static int shmPixmapPrivate; +#endif +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall() +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + + if (shmid != -1) + { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + else + { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + +void +ShmExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + if (nxagentOption(SharedMemory) == False) + { + return; + } + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + sharedPixmaps = nxagentOption(SharedPixmaps); + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + { + #ifdef TEST + fprintf(stderr, "ShmExtensionInit: Registering shmFuncs as miFuncs.\n"); + #endif + shmFuncs[i] = &miFuncs; + } + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; + if (sharedPixmaps) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } +#ifdef PIXPRIV + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } +#endif + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs( + ScreenPtr pScreen, + ShmFuncsPtr funcs) +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat( + ScreenPtr pScreen, + int format) +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; +#ifdef PIXPRIV + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; +#else + char *base = (char *) pPixmap->devPrivate.ptr; + + if (base != (pointer) (pPixmap + 1)) + { + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) + { + if (shmdesc->addr <= base && base <= shmdesc->addr + shmdesc->size) + break; + } + } + else + shmdesc = 0; +#endif + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + #ifdef TEST + fprintf(stderr, "ShmRegisterFbFuncs: Registering shmFuncs as fbFuncs.\n"); + #endif + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + xfree(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + nxagentShmTrap = 0; + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + { + nxagentShmTrap = 1; + return; + } + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + nxagentShmTrap = 1; + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); + nxagentShmTrap = 1; +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + int length; + char *newdata; + extern int nxagentImageLength(int, int, int, int, int); + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Called with drawable at [%p] GC at [%p] data at [%p].\n", + (void *) dst, (void *) pGC, (void *) data); + #endif + + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + + /* + * We updated the internal framebuffer, + * now we want to go on the real X. + */ + + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Realizing the PutImage with depth [%d] " + " format [%d] w [%d] h [%d] sx [%d] sy [%d] sw [%d] " + " sh [%d] dx [%d].\n", depth, format, w, h, + sx, sy, sw, sh, dx); + #endif + + length = nxagentImageLength(sw, sh, format, 0, depth); + + if ((newdata = xalloc(length)) != NULL) + { + fbGetImage((DrawablePtr) pPixmap, sx, sy, sw, sh, format, AllPlanes, newdata); + (*pGC->ops->PutImage)(dst, pGC, depth, dx, dy, sw, sh, 0, format, newdata); + + xfree(newdata); + } + else + { + #ifdef WARNING + fprintf(stderr, "fbShmPutImage: WARNING! Data allocation failed.\n"); + #endif + } + + FreeScratchPixmapHeader(pPixmap); + } + else + { + #ifdef TEST + fprintf(stderr, "fbShmPutImage: Calling miShmPutImage().\n"); + #endif + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); + } +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(register ClientPtr client) +{ + int j, result = 0, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != client->noClientException) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + + if (client->swapped) { + register int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static int +ProcPanoramiXShmCreatePixmap( + register ClientPtr client) +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + PanoramiXRes *newPix; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = (client->noClientException); + + FOR_NSCREENS(j) { + pScreen = screenInfo.screens[j]; + + pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + xfree(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Format [%d] srcX [%d] srcY [%d], " + "totalWidth [%d] totalHeight [%d]\n", stuff->format, stuff->srcX, + stuff->srcY, stuff->totalWidth, stuff->totalHeight); + #endif + + #ifdef TEST + fprintf(stderr, "ProcShmPutImage: Calling (*shmFuncs[pDraw->pScreen->myNum]->PutImage)().\n"); + #endif + + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + stuff->offset); + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else + { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + nxagentShmPixmapTrap = 1; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, width, height, depth); + + if (!pPixmap) + { + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + #ifdef TEST + fprintf(stderr,"fbShmCreatePixmap: Width [%d] Height [%d] Depth [%d]\n", width, height, depth); + #endif + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) + { + #ifdef WARNING + fprintf(stderr,"fbShmCreatePixmap: Return Null Pixmap.\n"); + #endif + + (*pScreen->DestroyPixmap)(pPixmap); + + nxagentShmPixmapTrap = 0; + + return NullPixmap; + } + + nxagentShmPixmapTrap = 0; + + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return(client->noClientException); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + + if (stuff->data <= X_ShmCreatePixmap) + { + fprintf(stderr, "ProcShmDispatch: Request [%s] OPCODE#%d.\n", + nxagentShmRequestLiteral[stuff->data], stuff->data); + } + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Going to execute ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + { + result = ProcPanoramiXShmPutImage(client); + + nxagentShmTrap = 0; + + return result; + } +#endif + + result = ProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcShmDispatch: Returning from ProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute operation [%d] for client [%d].\n", + stuff -> data, client -> index); + #endif + + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + { + int result; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Going to execute SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + nxagentShmTrap = 1; + + result = SProcShmPutImage(client); + + nxagentShmTrap = 0; + + #ifdef TEST + fprintf(stderr, "SProcShmDispatch: Returning from SProcShmPutImage() for client [%d].\n", + client -> index); + #endif + + return result; + } + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.X.original new file mode 100644 index 000000000..806008c60 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.X.original @@ -0,0 +1,1267 @@ +/* $XFree86: xc/programs/Xserver/Xext/shm.c,v 3.41 2003/12/17 23:28:56 alanh Exp $ */ +/************************************************************ + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */ + +#define SHM + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#ifndef Lynx +#include +#include +#else +#include +#include +#endif +#include +#include +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#define _XSHM_SERVER_ +#include +#include +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "modinit.h" + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +static void miShmPutImage(XSHM_PUT_IMAGE_ARGS); +static void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( + pointer /* value */, + XID /* shmseg */ + ); +static void ShmResetProc( + ExtensionEntry * /* extEntry */ + ); +static void SShmCompletionEvent( + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int pixmapFormat; +static int shmPixFormat[MAXSCREENS]; +static ShmFuncsPtr shmFuncs[MAXSCREENS]; +static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +#ifdef PIXPRIV +static int shmPixmapPrivate; +#endif +static ShmFuncs miFuncs = {NULL, miShmPutImage}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ + if (!shmdesc) \ + { \ + client->errorValue = shmseg; \ + return BadShmSegCode; \ + } \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(signo) +int signo; +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall() +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + + if (shmid != -1) + { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); + } + else + { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + +void +ShmExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + sharedPixmaps = xFalse; + pixmapFormat = 0; + { + sharedPixmaps = xTrue; + pixmapFormat = shmPixFormat[0]; + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!shmFuncs[i]) + shmFuncs[i] = &miFuncs; + if (!shmFuncs[i]->CreatePixmap) + sharedPixmaps = xFalse; + if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) + { + sharedPixmaps = xFalse; + pixmapFormat = 0; + } + } + if (!pixmapFormat) + pixmapFormat = ZPixmap; + if (sharedPixmaps) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } +#ifdef PIXPRIV + shmPixmapPrivate = AllocatePixmapPrivateIndex(); + for (i = 0; i < screenInfo.numScreens; i++) + { + if (!AllocatePixmapPrivate(screenInfo.screens[i], + shmPixmapPrivate, 0)) + return; + } +#endif + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc (extEntry) +ExtensionEntry *extEntry; +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + shmFuncs[i] = (ShmFuncsPtr)NULL; + shmPixFormat[i] = 0; + } +} + +void +ShmRegisterFuncs( + ScreenPtr pScreen, + ShmFuncsPtr funcs) +{ + shmFuncs[pScreen->myNum] = funcs; +} + +void +ShmSetPixmapFormat( + ScreenPtr pScreen, + int format) +{ + shmPixFormat[pScreen->myNum] = format; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; +#ifdef PIXPRIV + shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; +#else + char *base = (char *) pPixmap->devPrivate.ptr; + + if (base != (pointer) (pPixmap + 1)) + { + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) + { + if (shmdesc->addr <= base && base <= shmdesc->addr + shmdesc->size) + break; + } + } + else + shmdesc = 0; +#endif + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + ret = (*pScreen->DestroyPixmap) (pPixmap); + destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(pScreen) + ScreenPtr pScreen; +{ + shmFuncs[pScreen->myNum] = &fbFuncs; +} + +static int +ProcShmQueryVersion(client) + register ClientPtr client; +{ + xShmQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = pixmapFormat; + rep.majorVersion = SHM_MAJOR_VERSION; + rep.minorVersion = SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +{ + int uid, gid; + mode_t mask; + + if (LocalClientCred(client, &uid, &gid) != -1) { + + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (perm->uid == uid || perm->cuid == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + /* Check the group */ + if (perm->gid == gid || perm->cgid == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (perm->mode & mask) == mask ? 0 : -1; + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (perm->mode & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(client) + register ClientPtr client; +{ + struct shmid_ds buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + shmctl(stuff->shmid, IPC_STAT, &buf)) + { + xfree(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + xfree(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = buf.shm_segsz; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return(client->noClientException); +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(value, shmseg) + pointer value; /* must conform to DeleteType */ + XID shmseg; +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + xfree(shmdesc); + return Success; +} + +static int +ProcShmDetach(client) + register ClientPtr client; +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return(client->noClientException); +} + +static void +miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + PixmapPtr pmap; + GCPtr putGC; + + putGC = GetScratchGC(depth, dst->pScreen); + if (!putGC) + return; + pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); + if (!pmap) + { + FreeScratchGC(putGC); + return; + } + ValidateGC((DrawablePtr)pmap, putGC); + (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pmap->drawable.pScreen->DestroyPixmap)(pmap); +} + +static void +fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) + DrawablePtr dst; + GCPtr pGC; + int depth, w, h, sx, sy, sw, sh, dx, dy; + unsigned int format; + char *data; +{ + if ((format == ZPixmap) || (depth == 1)) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return; + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, + sx, sy, sw, sh, dx, dy); + FreeScratchPixmapHeader(pPixmap); + } + else + miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(register ClientPtr client) +{ + int j, result = 0, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != client->noClientException) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) + VERIFY_DRAWABLE(drawables[i], draw->info[i].id, client); + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + + if (client->swapped) { + register int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static int +ProcPanoramiXShmCreatePixmap( + register ClientPtr client) +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + PanoramiXRes *newPix; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + + if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = (client->noClientException); + + FOR_NSCREENS(j) { + pScreen = screenInfo.screens[j]; + + pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + xfree(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(client) + register ClientPtr client; +{ + register GCPtr pGC; + register DrawablePtr pDraw; + long length; + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + client); + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || + ((stuff->format != ZPixmap) && + (stuff->srcX < screenInfo.bitmapScanlinePad) && + ((stuff->format == XYBitmap) || + ((stuff->srcY == 0) && + (stuff->srcHeight == stuff->totalHeight))))) && + ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, + stuff->dstX, stuff->dstY, + stuff->totalWidth, stuff->srcHeight, + stuff->srcX, stuff->format, + shmdesc->addr + stuff->offset + + (stuff->srcY * length)); + else + (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( + pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + stuff->offset); + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return (client->noClientException); +} + + + +static int +ProcShmGetImage(client) + register ClientPtr client; +{ + register DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + VERIFY_DRAWABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else + { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return(client->noClientException); +} + +static PixmapPtr +fbShmCreatePixmap (pScreen, width, height, depth, addr) + ScreenPtr pScreen; + int width; + int height; + int depth; + char *addr; +{ + register PixmapPtr pPixmap; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); + if (!pPixmap) + return NullPixmap; + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { + (*pScreen->DestroyPixmap)(pPixmap); + return NullPixmap; + } + return pPixmap; +} + +static int +ProcShmCreatePixmap(client) + register ClientPtr client; +{ + PixmapPtr pMap; + register DrawablePtr pDraw; + DepthPtr pDepth; + register int i; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + VERIFY_SHMSIZE(shmdesc, stuff->offset, + PixmapBytePad(stuff->width, stuff->depth) * stuff->height, + client); + pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { +#ifdef PIXPRIV + pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; +#endif + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return(client->noClientException); + } + } + return (BadAlloc); +} + +static int +ProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmPutImage(client); +#endif + return ProcShmPutImage(client); + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(from, to) + xShmCompletionEvent *from, *to; +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(client) + register ClientPtr client; +{ + register int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(client) + ClientPtr client; +{ + register int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + return SProcShmPutImage(client); + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c new file mode 100644 index 000000000..7ba468ac0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c @@ -0,0 +1,4174 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.12 2005/07/03 08:53:38 daniels Exp $ */ +/* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/window.c,v 3.36 2003/11/14 23:52:50 torrey Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "selection.h" +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif +#include "dixevents.h" +#include "globals.h" + +#ifdef XAPPGROUP +#include +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif + +#include "Screen.h" +#include "Options.h" +#include "Atoms.h" +#include "Clipboard.h" +#include "Splash.h" +#include "Rootless.h" +#include "Composite.h" +#include "Drawable.h" +#include "Colormap.h" + +extern Bool nxagentWMIsRunning; +extern Bool nxagentScreenTrap; + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +int screenIsSaved = SCREEN_SAVER_OFF; + +ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#if 0 +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +#endif + +static Bool TileScreenSaver(int i, int kind); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int numSaveUndersViewable = 0; +int deltaSaveUndersViewable = 0; + +WindowPtr nxagentRootTileWindow; + +/* + * This block used the DEBUG symbol. + */ + +#ifdef WINDOW_TREE_DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(WindowPtr p1, int indent) +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; idrawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; iclipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +int +TraverseTree(register WindowPtr pWin, VisitWindowProcPtr func, pointer data) +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +int +WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data) +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +Bool enableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +SetWindowToDefaults(register WindowPtr pWin) +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +#ifdef COMPOSITE + pWin->redirectDraw = 0; +#endif +} + +#ifdef NXAGENT_SERVER + +void nxagentClearSplash(WindowPtr pW) +{ + int w, h; + ScreenPtr pScreen; + + w = pW->drawable.width; + h = pW->drawable.height; + + pScreen = pW->drawable.pScreen; + + if (pW->backgroundState == BackgroundPixmap) + { + (*pScreen->DestroyPixmap)(pW->background.pixmap); + } + + pW->backgroundState = BackgroundPixel; + pW->background.pixel = nxagentLogoBlack; + + (*pScreen->ChangeWindowAttributes)(pW, CWBackPixmap|CWBackPixel); +} + +static void +#if NeedFunctionPrototypes +MakeRootTile(WindowPtr pWin) +#else +MakeRootTile(pWin) + WindowPtr pWin; +#endif +{ + nxagentRootTileWindow = pWin; +} + +#else /* NXAGENT_SERVER */ + +static void +MakeRootTile(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + GCPtr pGC; + unsigned char back[128]; + int len = BitmapBytePad(sizeof(long)); + register unsigned char *from, *to; + register int i, j; + + pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4, + pScreen->rootDepth); + + pWin->backgroundState = BackgroundPixmap; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pWin->background.pixmap || !pGC) + FatalError("could not create root tile"); + + { + CARD32 attributes[2]; + + attributes[0] = pScreen->whitePixel; + attributes[1] = pScreen->blackPixel; + + (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); + } + + ValidateGC((DrawablePtr)pWin->background.pixmap, pGC); + + from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb; + to = back; + + for (i = 4; i > 0; i--, from++) + for (j = len; j > 0; j--) + *to++ = *from; + + if (blackRoot) + bzero(back, sizeof(back)); + + (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, + 0, 0, len, 4, 0, XYBitmap, (char *)back); + + FreeScratchGC(pGC); + +} + +#endif /* NXAGENT_SERVER */ + +WindowPtr +AllocateWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; + pWin->optional->inputShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + { + pScreen -> backingStoreSupport = NotUseful; + } + + if (enableBackingStore) + { + pScreen -> backingStoreSupport = Always; + } + + pScreen->saveUnderSupport = False; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +#ifdef NXAGENT_SERVER + +void +InitRootWindow(WindowPtr pWin) +{ + ScreenPtr pScreen; + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Called for window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (nxagentOption(Rootless)) + { + #ifdef TEST + fprintf(stderr, "InitRootWindow: Assigned agent root to window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + nxagentRootlessWindow = pWin; + } + + pScreen = pWin->drawable.pScreen; + + /* + * A root window is created for each screen by main + * and the pointer is saved in WindowTable as in the + * following snippet: + * + * for (i = 0; i < screenInfo.numScreens; i++) + * InitRootWindow(WindowTable[i]); + * + * Our root window on the real display was already + * created at the time the screen was opened, so it + * is unclear how this window (or the other window, + * if you prefer) fits in the big picture. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Going to create window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Created window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + + #ifdef NXAGENT_SPLASH + /* We SHOULD check for an error value here XXX */ + pWin -> background.pixel = pScreen -> blackPixel; + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixel|CWBorderPixel|CWCursor|CWBackingStore); + #else + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + #endif + + MakeRootTile(pWin); + + /* + * Map both the root and the default agent window. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Mapping default windows.\n"); + #endif + + nxagentInitAtoms(pWin); + + nxagentInitClipboard(pWin); + + nxagentMapDefaultWindows(); + + nxagentRedirectDefaultWindows(); + + #ifdef NXAGENT_ARTSD + { + char artsd_port[10]; + int nPort; + extern void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port); + nPort = atoi(display) + 7000; + sprintf(artsd_port,"%d", nPort); + nxagentPropagateArtsdProperties(pScreen, artsd_port); + } + #endif +} + +#else /* NXAGENT_SERVER */ + +void +InitRootWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + MakeRootTile(pWin); + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + + MapWindow(pWin, serverClient); +} + +#endif /* NXAGENT_SERVER */ + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(register WindowPtr pWin, RegionPtr Rgn, + register int x, register int y, + register int w, register int h) +{ +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +WindowPtr +RealChildHead(register WindowPtr pWin) +{ + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +WindowPtr +CreateWindow(Window wid, register WindowPtr pParent, int x, int y, unsigned w, + unsigned h, unsigned bw, unsigned class, register Mask vmask, XID *vlist, + int depth, ClientPtr client, VisualID visual, int *error) +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (client->trustLevel != XSecurityClientTrusted) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_NULL(pScreen, &pWin->clipList); + REGION_NULL(pScreen, &pWin->borderClip); + REGION_NULL(pScreen, &pWin->winSize); + REGION_NULL(pScreen, &pWin->borderSize); + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + return pWin; +} + +static void +FreeWindowResources(register WindowPtr pWin) +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); + if (wInputShape (pWin)) + REGION_DESTROY(pScreen, wInputShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +CrushTree(WindowPtr pWin) +{ + register WindowPtr pChild, pSib, pParent; + UnrealizeWindowProcPtr UnrealizeWindow; + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +int +DeleteWindow(pointer value, XID wid) + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + + if (pWin -> optional && + pWin -> optional -> colormap && + pWin -> parent) + { + nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen); + } + + xfree(pWin); + return Success; +} + +void +DestroySubwindows(register WindowPtr pWin, ClientPtr client) +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +int +ChangeWindowAttributes(register WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) +{ + register Mask index2; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index2 = (Mask) lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows */ + if (client->trustLevel == XSecurityClientTrusted) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XCSECURITY + } + else + { /* didn't change the background to None, so don't tell ddx */ + index2 = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index2 = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + + #ifdef TEST + fprintf(stderr, "ChangeWindowAttributes: Changed backing store value to %d for window at %p.\n", + val, (void*)pWin); + #endif + + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == (CARD32)~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + /* + * TODO: Some applications like java bean shell + * don' t work if they cannot monitor the root + * window for Structure Redirect events. However + * this doesn't seem to be the best solution, since + * also an X server with a window manager running, + * doesn't allow to monitor for those events, but + * the java bean shell works flawlessy on this + * server. + * + * if (nxagentCheckIllegalRootMonitoring(pWin, (Mask)*pVlist)) + * { + * return BadAccess; + * } + */ + + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if ( win_owner && win_owner->appgroup && + !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index2; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_NULL(pScreen, &exposed); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(register WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply *wa) +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +WindowPtr +MoveWindowInStack(register WindowPtr pWin, register WindowPtr pNextSib) +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + WindowPtr pOldNextSib = pWin->nextSib; + + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + if(pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); + } + +#ifdef ROOTLESS + /* + * In rootless mode we can't optimize away window restacks. + * There may be non-X windows around, so even if the window + * is in the correct position from X's point of view, + * the underlying window system may want to reorder it. + */ + else if (pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib); +#endif + + return( pFirstChange ); +} + +RegionPtr +CreateUnclippedWinSize (register WindowPtr pWin) +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +void +SetWinSize (register WindowPtr pWin) +{ +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + pWin->drawable.width; + box.y2 = pWin->drawable.y + pWin->drawable.height; + REGION_RESET (pScreen, &pWin->winSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +void +SetBorderSize (register WindowPtr pWin) +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x - bw; + box.y1 = pWin->drawable.y - bw; + box.x2 = pWin->drawable.x + pWin->drawable.width + bw; + box.y2 = pWin->drawable.y + pWin->drawable.height + bw; + REGION_RESET (pScreen, &pWin->borderSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +/** + * + * \param x,y new window position + * \param oldx,oldy old window position + * \param destx,desty position relative to gravity + */ + +void +GravityTranslate (register int x, register int y, int oldx, int oldy, + int dw, int dh, unsigned gravity, + register int *destx, register int *desty) +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +void +ResizeChildrenWinSize(register WindowPtr pWin, int dx, int dy, int dw, int dh) +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + + /* + * Don't force X to move children. It will position them + * according with gravity. + * + * (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + */ + + /* + * Update pSib privates, as this window is moved by X. + */ + + nxagentAddConfiguredWindow(pSib, CW_Update); + + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + + (*pScreen->PositionWindow)(pChild, pChild->drawable.x, + pChild->drawable.y); + + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +IsSiblingAboveMe( + register WindowPtr pMe, + register WindowPtr pSib) +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +WindowExtents( + register WindowPtr pWin, + register BoxPtr pBox) +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +MakeBoundingRegion ( + register WindowPtr pWin, + BoxPtr pBox) +{ + RegionPtr pRgn; +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +ShapeOverlap ( + WindowPtr pWin, + BoxPtr pWinBox, + WindowPtr pSib, + BoxPtr pSibBox) +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +AnyWindowOverlapsMe( + WindowPtr pWin, + WindowPtr pHead, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +IOverlapAnyWindow( + WindowPtr pWin, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +WhereDoIGoInTheStack( + register WindowPtr pWin, + register WindowPtr pSib, + short x, + short y, + unsigned short w, + unsigned short h, + int smode) +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +ReflectStackChange( + register WindowPtr pWin, + register WindowPtr pSib, + VTKind kind) +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!pWin->parent) + return; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(register WindowPtr pWin, register Mask mask, XID *vlist, ClientPtr client) +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid = 0; + Mask index2, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index2 = (Mask)lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + + fprintf(stderr, "ConfigureWindow: pWin [%p] mask [%lu] client [%p]\n", + pWin, mask, client); + + fprintf(stderr, "ConfigureWindow: x [%d] y [%d] w [%d] h [%d] CWStackMode [%d] " + "smode [%d] pSib [%p]\n", + x, y, w, h, (mask & CWStackMode) ? 1 : 0, smode, pSib); + } + #endif + + if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin) && + pWin -> overrideRedirect == 0 && + nxagentScreenTrap == 0) + { + nxagentConfigureRootlessWindow(pWin, x, y, w, h, bw, pSib, smode, mask); + + return Success; + } + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureRequest.x += panoramiXdataPtr[0].x; + event.u.configureRequest.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { +#ifndef ROOTLESS + /* See above for why we always reorder in rootless mode. */ + if (pWin->nextSib != pSib) +#endif + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureNotify.x += panoramiXdataPtr[0].x; + event.u.configureNotify.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + + nxagentFlushConfigureWindow(); + + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(WindowPtr pParent, int direction, ClientPtr client) +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + #ifdef TEST + fprintf(stderr, "CirculateWindow: pParent [%p] direction [%d] client [%p]\n", + pParent, direction, client); + #endif + + /* + * if (nxagentOption(Rootless) && nxagentWMIsRunning && + * nxagentWindowTopLevel(pWin) && pWin -> overrideRedirect == 0) + * { + * nxagentCirculateRootlessWindows(direction); + * return Success; + * } + */ + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +CompareWIDs( + WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(register WindowPtr pWin, register WindowPtr pParent, + int x, int y, ClientPtr client) +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pParent->parent) { + event.u.reparent.x += panoramiXdataPtr[0].x; + event.u.reparent.y += panoramiXdataPtr[0].y; + } +#endif + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + + if (pWin->parent == WindowTable[0]) + { + nxagentSetTopLevelEventMask(pWin); + } + + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +RealizeTree(WindowPtr pWin) +{ + register WindowPtr pChild; + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +int +MapWindow(register WindowPtr pWin, ClientPtr client) +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "MapWindow: pWin [%p] client [%p]\n", pWin, client); + } + #endif + + if (pWin->mapped) + return(Success); + +#ifdef XCSECURITY + /* don't let an untrusted client map a child-of-trusted-window, InputOnly + * window; too easy to steal device input + */ + if ( (client->trustLevel != XSecurityClientTrusted) && + (pWin->drawable.class == InputOnly) && + (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) ) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_NULL(pScreen, &temp); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + nxagentFlushConfigureWindow(); + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(register WindowPtr pParent, ClientPtr client) +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +UnrealizeTree( + WindowPtr pWin, + Bool fromConfigure) +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { + PanoramiXRes *win; + win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, + XRT_WINDOW); + if(win) + win->u.win.visibility = VisibilityNotViewable; + } +#endif + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +int +UnmapWindow(register WindowPtr pWin, Bool fromConfigure) +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "UnmapWindow: pWin [%p] fromConfigure [%d]\n", pWin, + fromConfigure); + } + #endif + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(register WindowPtr pWin) +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin = NULL; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(register ClientPtr client) +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; jnumSaved; j++) + { + pWin = SaveSetWindow(client->saveSet[j]); +#ifdef XFIXES + if (SaveSetToRoot(client->saveSet[j])) + pParent = WindowTable[pWin->drawable.pScreen->myNum]; + else +#endif + { + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + } + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } +#ifdef XFIXES + if (SaveSetRemap (client->saveSet[j])) +#endif + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; +} + +/** + * + * \param x,y in root + * \param box "return" value + */ +Bool +VisibleBoundingBoxFromPoint(register WindowPtr pWin, int x, int y, BoxPtr box) +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +/** + * + * \param x,y in root + */ +Bool +PointInWindowIsVisible(register WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return(TRUE); + return(FALSE); +} + + +RegionPtr +NotClippedByChildren(register WindowPtr pWin) +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + +void +SendVisibilityNotify(WindowPtr pWin) +{ + xEvent event; +#ifndef NO_XINERAMA_PORT + unsigned int visibility = pWin->visibility; +#endif +#ifdef PANORAMIX + /* This is not quite correct yet, but it's close */ + if(!noPanoramiXExtension) { + PanoramiXRes *win; + WindowPtr pWin2; + int i, Scrnum; + + Scrnum = pWin->drawable.pScreen->myNum; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); + + if(!win || (win->u.win.visibility == visibility)) + return; + + switch(visibility) { + case VisibilityUnobscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility == VisibilityPartiallyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + case VisibilityPartiallyObscured: + if(Scrnum) { + pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); + if (pWin2) pWin = pWin2; + } + break; + case VisibilityFullyObscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility != VisibilityFullyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + } + + win->u.win.visibility = visibility; + } +#endif + + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +static void DrawLogo( + WindowPtr pWin +); +#endif + +void +SaveScreens(int on, int mode) +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if (nxagentOption(Timeout) != 0) + { + #ifdef TEST + fprintf(stderr, "SaveScreens: An external screen-saver handler is installed. " + "Ignoring it to let the auto-disconnect feature work.\n"); + #endif + } + else + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + /* + * Call the DDX saver in case it wants to do something + * at cycle time + */ + else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + type); + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; + if (mode == ScreenSaverReset) + SetScreenSaverTimer(); +} + +static Bool +TileScreenSaver(int i, int kind) +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID = 0; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; jwidth + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +WindowPtr +FindWindowWithOptional (register WindowPtr w) +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +void +CheckWindowOptionalNeed (register WindowPtr w) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; + if (optional->inputShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +Bool +MakeWindowOptional (register WindowPtr pWin) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; + optional->inputShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (register WindowPtr pWin) +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + /* + * TOG changed this code to: + * + * if (pWin->cursorIsNone == FALSE) + * FreeCursor (pWin->optional->cursor, (Cursor)0); + * pWin->cursorIsNone = TRUE; + * + * This is blatently wrong; windows without optionals can have + * two different cursor values, either None or sharing their + * parents cursor. This difference is controlled by the + * cursorIsNone value; when TRUE, the window has no cursor, + * when false, it shares its cursor with its parent; TOG + * made it impossible for a window to have a cursor without + * an optional record. + */ + if (pWin->optional->cursor) + { + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = FALSE; + } + else + pWin->cursorIsNone = TRUE; +/* FIXME + There is an error when disposing ClientResources on Agent exit + this xfree is not valid in some window at exit +*/ + + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +DrawLogo(WindowPtr pWin) +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.NX.original new file mode 100644 index 000000000..7ba468ac0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.NX.original @@ -0,0 +1,4174 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.12 2005/07/03 08:53:38 daniels Exp $ */ +/* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/window.c,v 3.36 2003/11/14 23:52:50 torrey Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "selection.h" +#ifdef PANORAMIX +#include "../../Xext/panoramiX.h" +#include "../../Xext/panoramiXsrv.h" +#endif +#include "dixevents.h" +#include "globals.h" + +#ifdef XAPPGROUP +#include +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif + +#include "Screen.h" +#include "Options.h" +#include "Atoms.h" +#include "Clipboard.h" +#include "Splash.h" +#include "Rootless.h" +#include "Composite.h" +#include "Drawable.h" +#include "Colormap.h" + +extern Bool nxagentWMIsRunning; +extern Bool nxagentScreenTrap; + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +int screenIsSaved = SCREEN_SAVER_OFF; + +ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#if 0 +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +#endif + +static Bool TileScreenSaver(int i, int kind); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +int numSaveUndersViewable = 0; +int deltaSaveUndersViewable = 0; + +WindowPtr nxagentRootTileWindow; + +/* + * This block used the DEBUG symbol. + */ + +#ifdef WINDOW_TREE_DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(WindowPtr p1, int indent) +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; idrawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; iclipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +int +TraverseTree(register WindowPtr pWin, VisitWindowProcPtr func, pointer data) +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +int +WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data) +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +Bool enableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +SetWindowToDefaults(register WindowPtr pWin) +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +#ifdef COMPOSITE + pWin->redirectDraw = 0; +#endif +} + +#ifdef NXAGENT_SERVER + +void nxagentClearSplash(WindowPtr pW) +{ + int w, h; + ScreenPtr pScreen; + + w = pW->drawable.width; + h = pW->drawable.height; + + pScreen = pW->drawable.pScreen; + + if (pW->backgroundState == BackgroundPixmap) + { + (*pScreen->DestroyPixmap)(pW->background.pixmap); + } + + pW->backgroundState = BackgroundPixel; + pW->background.pixel = nxagentLogoBlack; + + (*pScreen->ChangeWindowAttributes)(pW, CWBackPixmap|CWBackPixel); +} + +static void +#if NeedFunctionPrototypes +MakeRootTile(WindowPtr pWin) +#else +MakeRootTile(pWin) + WindowPtr pWin; +#endif +{ + nxagentRootTileWindow = pWin; +} + +#else /* NXAGENT_SERVER */ + +static void +MakeRootTile(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + GCPtr pGC; + unsigned char back[128]; + int len = BitmapBytePad(sizeof(long)); + register unsigned char *from, *to; + register int i, j; + + pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4, + pScreen->rootDepth); + + pWin->backgroundState = BackgroundPixmap; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pWin->background.pixmap || !pGC) + FatalError("could not create root tile"); + + { + CARD32 attributes[2]; + + attributes[0] = pScreen->whitePixel; + attributes[1] = pScreen->blackPixel; + + (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); + } + + ValidateGC((DrawablePtr)pWin->background.pixmap, pGC); + + from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb; + to = back; + + for (i = 4; i > 0; i--, from++) + for (j = len; j > 0; j--) + *to++ = *from; + + if (blackRoot) + bzero(back, sizeof(back)); + + (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, + 0, 0, len, 4, 0, XYBitmap, (char *)back); + + FreeScratchGC(pGC); + +} + +#endif /* NXAGENT_SERVER */ + +WindowPtr +AllocateWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; + pWin->optional->inputShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + { + pScreen -> backingStoreSupport = NotUseful; + } + + if (enableBackingStore) + { + pScreen -> backingStoreSupport = Always; + } + + pScreen->saveUnderSupport = False; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +#ifdef NXAGENT_SERVER + +void +InitRootWindow(WindowPtr pWin) +{ + ScreenPtr pScreen; + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Called for window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (nxagentOption(Rootless)) + { + #ifdef TEST + fprintf(stderr, "InitRootWindow: Assigned agent root to window at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + nxagentRootlessWindow = pWin; + } + + pScreen = pWin->drawable.pScreen; + + /* + * A root window is created for each screen by main + * and the pointer is saved in WindowTable as in the + * following snippet: + * + * for (i = 0; i < screenInfo.numScreens; i++) + * InitRootWindow(WindowTable[i]); + * + * Our root window on the real display was already + * created at the time the screen was opened, so it + * is unclear how this window (or the other window, + * if you prefer) fits in the big picture. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Going to create window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Created window as root at [%p][%ld] with parent [%p].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin -> parent); + #endif + + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + + #ifdef NXAGENT_SPLASH + /* We SHOULD check for an error value here XXX */ + pWin -> background.pixel = pScreen -> blackPixel; + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixel|CWBorderPixel|CWCursor|CWBackingStore); + #else + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + #endif + + MakeRootTile(pWin); + + /* + * Map both the root and the default agent window. + */ + + #ifdef TEST + fprintf(stderr, "InitRootWindow: Mapping default windows.\n"); + #endif + + nxagentInitAtoms(pWin); + + nxagentInitClipboard(pWin); + + nxagentMapDefaultWindows(); + + nxagentRedirectDefaultWindows(); + + #ifdef NXAGENT_ARTSD + { + char artsd_port[10]; + int nPort; + extern void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port); + nPort = atoi(display) + 7000; + sprintf(artsd_port,"%d", nPort); + nxagentPropagateArtsdProperties(pScreen, artsd_port); + } + #endif +} + +#else /* NXAGENT_SERVER */ + +void +InitRootWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + MakeRootTile(pWin); + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + + MapWindow(pWin, serverClient); +} + +#endif /* NXAGENT_SERVER */ + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(register WindowPtr pWin, RegionPtr Rgn, + register int x, register int y, + register int w, register int h) +{ +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +WindowPtr +RealChildHead(register WindowPtr pWin) +{ + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +WindowPtr +CreateWindow(Window wid, register WindowPtr pParent, int x, int y, unsigned w, + unsigned h, unsigned bw, unsigned class, register Mask vmask, XID *vlist, + int depth, ClientPtr client, VisualID visual, int *error) +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (client->trustLevel != XSecurityClientTrusted) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_NULL(pScreen, &pWin->clipList); + REGION_NULL(pScreen, &pWin->borderClip); + REGION_NULL(pScreen, &pWin->winSize); + REGION_NULL(pScreen, &pWin->borderSize); + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + return pWin; +} + +static void +FreeWindowResources(register WindowPtr pWin) +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); + if (wInputShape (pWin)) + REGION_DESTROY(pScreen, wInputShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +CrushTree(WindowPtr pWin) +{ + register WindowPtr pChild, pSib, pParent; + UnrealizeWindowProcPtr UnrealizeWindow; + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +int +DeleteWindow(pointer value, XID wid) + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + + if (pWin -> optional && + pWin -> optional -> colormap && + pWin -> parent) + { + nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen); + } + + xfree(pWin); + return Success; +} + +void +DestroySubwindows(register WindowPtr pWin, ClientPtr client) +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +int +ChangeWindowAttributes(register WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) +{ + register Mask index2; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index2 = (Mask) lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows */ + if (client->trustLevel == XSecurityClientTrusted) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XCSECURITY + } + else + { /* didn't change the background to None, so don't tell ddx */ + index2 = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index2 = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + + #ifdef TEST + fprintf(stderr, "ChangeWindowAttributes: Changed backing store value to %d for window at %p.\n", + val, (void*)pWin); + #endif + + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == (CARD32)~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + /* + * TODO: Some applications like java bean shell + * don' t work if they cannot monitor the root + * window for Structure Redirect events. However + * this doesn't seem to be the best solution, since + * also an X server with a window manager running, + * doesn't allow to monitor for those events, but + * the java bean shell works flawlessy on this + * server. + * + * if (nxagentCheckIllegalRootMonitoring(pWin, (Mask)*pVlist)) + * { + * return BadAccess; + * } + */ + + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if ( win_owner && win_owner->appgroup && + !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index2; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_NULL(pScreen, &exposed); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(register WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply *wa) +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +WindowPtr +MoveWindowInStack(register WindowPtr pWin, register WindowPtr pNextSib) +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + WindowPtr pOldNextSib = pWin->nextSib; + + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + if(pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); + } + +#ifdef ROOTLESS + /* + * In rootless mode we can't optimize away window restacks. + * There may be non-X windows around, so even if the window + * is in the correct position from X's point of view, + * the underlying window system may want to reorder it. + */ + else if (pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib); +#endif + + return( pFirstChange ); +} + +RegionPtr +CreateUnclippedWinSize (register WindowPtr pWin) +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +void +SetWinSize (register WindowPtr pWin) +{ +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + pWin->drawable.width; + box.y2 = pWin->drawable.y + pWin->drawable.height; + REGION_RESET (pScreen, &pWin->winSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +void +SetBorderSize (register WindowPtr pWin) +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x - bw; + box.y1 = pWin->drawable.y - bw; + box.x2 = pWin->drawable.x + pWin->drawable.width + bw; + box.y2 = pWin->drawable.y + pWin->drawable.height + bw; + REGION_RESET (pScreen, &pWin->borderSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +/** + * + * \param x,y new window position + * \param oldx,oldy old window position + * \param destx,desty position relative to gravity + */ + +void +GravityTranslate (register int x, register int y, int oldx, int oldy, + int dw, int dh, unsigned gravity, + register int *destx, register int *desty) +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +void +ResizeChildrenWinSize(register WindowPtr pWin, int dx, int dy, int dw, int dh) +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + + /* + * Don't force X to move children. It will position them + * according with gravity. + * + * (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + */ + + /* + * Update pSib privates, as this window is moved by X. + */ + + nxagentAddConfiguredWindow(pSib, CW_Update); + + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + + (*pScreen->PositionWindow)(pChild, pChild->drawable.x, + pChild->drawable.y); + + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +IsSiblingAboveMe( + register WindowPtr pMe, + register WindowPtr pSib) +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +WindowExtents( + register WindowPtr pWin, + register BoxPtr pBox) +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +MakeBoundingRegion ( + register WindowPtr pWin, + BoxPtr pBox) +{ + RegionPtr pRgn; +#ifndef NXAGENT_SERVER + ScreenPtr pScreen = pWin->drawable.pScreen; +#endif /* NXAGENT_SERVER */ + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +ShapeOverlap ( + WindowPtr pWin, + BoxPtr pWinBox, + WindowPtr pSib, + BoxPtr pSibBox) +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +AnyWindowOverlapsMe( + WindowPtr pWin, + WindowPtr pHead, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +IOverlapAnyWindow( + WindowPtr pWin, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +WhereDoIGoInTheStack( + register WindowPtr pWin, + register WindowPtr pSib, + short x, + short y, + unsigned short w, + unsigned short h, + int smode) +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +ReflectStackChange( + register WindowPtr pWin, + register WindowPtr pSib, + VTKind kind) +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!pWin->parent) + return; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(register WindowPtr pWin, register Mask mask, XID *vlist, ClientPtr client) +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid = 0; + Mask index2, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index2 = (Mask)lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + + fprintf(stderr, "ConfigureWindow: pWin [%p] mask [%lu] client [%p]\n", + pWin, mask, client); + + fprintf(stderr, "ConfigureWindow: x [%d] y [%d] w [%d] h [%d] CWStackMode [%d] " + "smode [%d] pSib [%p]\n", + x, y, w, h, (mask & CWStackMode) ? 1 : 0, smode, pSib); + } + #endif + + if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin) && + pWin -> overrideRedirect == 0 && + nxagentScreenTrap == 0) + { + nxagentConfigureRootlessWindow(pWin, x, y, w, h, bw, pSib, smode, mask); + + return Success; + } + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureRequest.x += panoramiXdataPtr[0].x; + event.u.configureRequest.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { +#ifndef ROOTLESS + /* See above for why we always reorder in rootless mode. */ + if (pWin->nextSib != pSib) +#endif + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureNotify.x += panoramiXdataPtr[0].x; + event.u.configureNotify.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + + nxagentFlushConfigureWindow(); + + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(WindowPtr pParent, int direction, ClientPtr client) +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + #ifdef TEST + fprintf(stderr, "CirculateWindow: pParent [%p] direction [%d] client [%p]\n", + pParent, direction, client); + #endif + + /* + * if (nxagentOption(Rootless) && nxagentWMIsRunning && + * nxagentWindowTopLevel(pWin) && pWin -> overrideRedirect == 0) + * { + * nxagentCirculateRootlessWindows(direction); + * return Success; + * } + */ + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +CompareWIDs( + WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(register WindowPtr pWin, register WindowPtr pParent, + int x, int y, ClientPtr client) +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pParent->parent) { + event.u.reparent.x += panoramiXdataPtr[0].x; + event.u.reparent.y += panoramiXdataPtr[0].y; + } +#endif + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + + if (pWin->parent == WindowTable[0]) + { + nxagentSetTopLevelEventMask(pWin); + } + + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +RealizeTree(WindowPtr pWin) +{ + register WindowPtr pChild; + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +int +MapWindow(register WindowPtr pWin, ClientPtr client) +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "MapWindow: pWin [%p] client [%p]\n", pWin, client); + } + #endif + + if (pWin->mapped) + return(Success); + +#ifdef XCSECURITY + /* don't let an untrusted client map a child-of-trusted-window, InputOnly + * window; too easy to steal device input + */ + if ( (client->trustLevel != XSecurityClientTrusted) && + (pWin->drawable.class == InputOnly) && + (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) ) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_NULL(pScreen, &temp); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + nxagentFlushConfigureWindow(); + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(register WindowPtr pParent, ClientPtr client) +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +UnrealizeTree( + WindowPtr pWin, + Bool fromConfigure) +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { + PanoramiXRes *win; + win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, + XRT_WINDOW); + if(win) + win->u.win.visibility = VisibilityNotViewable; + } +#endif + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +int +UnmapWindow(register WindowPtr pWin, Bool fromConfigure) +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + #ifdef TEST + if (nxagentWindowTopLevel(pWin)) + { + fprintf(stderr, "UnmapWindow: pWin [%p] fromConfigure [%d]\n", pWin, + fromConfigure); + } + #endif + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(register WindowPtr pWin) +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin = NULL; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(register ClientPtr client) +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; jnumSaved; j++) + { + pWin = SaveSetWindow(client->saveSet[j]); +#ifdef XFIXES + if (SaveSetToRoot(client->saveSet[j])) + pParent = WindowTable[pWin->drawable.pScreen->myNum]; + else +#endif + { + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + } + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } +#ifdef XFIXES + if (SaveSetRemap (client->saveSet[j])) +#endif + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; +} + +/** + * + * \param x,y in root + * \param box "return" value + */ +Bool +VisibleBoundingBoxFromPoint(register WindowPtr pWin, int x, int y, BoxPtr box) +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +/** + * + * \param x,y in root + */ +Bool +PointInWindowIsVisible(register WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return(TRUE); + return(FALSE); +} + + +RegionPtr +NotClippedByChildren(register WindowPtr pWin) +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + +void +SendVisibilityNotify(WindowPtr pWin) +{ + xEvent event; +#ifndef NO_XINERAMA_PORT + unsigned int visibility = pWin->visibility; +#endif +#ifdef PANORAMIX + /* This is not quite correct yet, but it's close */ + if(!noPanoramiXExtension) { + PanoramiXRes *win; + WindowPtr pWin2; + int i, Scrnum; + + Scrnum = pWin->drawable.pScreen->myNum; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); + + if(!win || (win->u.win.visibility == visibility)) + return; + + switch(visibility) { + case VisibilityUnobscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility == VisibilityPartiallyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + case VisibilityPartiallyObscured: + if(Scrnum) { + pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); + if (pWin2) pWin = pWin2; + } + break; + case VisibilityFullyObscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility != VisibilityFullyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + } + + win->u.win.visibility = visibility; + } +#endif + + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +static void DrawLogo( + WindowPtr pWin +); +#endif + +void +SaveScreens(int on, int mode) +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if (nxagentOption(Timeout) != 0) + { + #ifdef TEST + fprintf(stderr, "SaveScreens: An external screen-saver handler is installed. " + "Ignoring it to let the auto-disconnect feature work.\n"); + #endif + } + else + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + /* + * Call the DDX saver in case it wants to do something + * at cycle time + */ + else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + type); + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; + if (mode == ScreenSaverReset) + SetScreenSaverTimer(); +} + +static Bool +TileScreenSaver(int i, int kind) +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID = 0; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; jwidth + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +WindowPtr +FindWindowWithOptional (register WindowPtr w) +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +void +CheckWindowOptionalNeed (register WindowPtr w) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; + if (optional->inputShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +Bool +MakeWindowOptional (register WindowPtr pWin) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; + optional->inputShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (register WindowPtr pWin) +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + /* + * TOG changed this code to: + * + * if (pWin->cursorIsNone == FALSE) + * FreeCursor (pWin->optional->cursor, (Cursor)0); + * pWin->cursorIsNone = TRUE; + * + * This is blatently wrong; windows without optionals can have + * two different cursor values, either None or sharing their + * parents cursor. This difference is controlled by the + * cursorIsNone value; when TRUE, the window has no cursor, + * when false, it shares its cursor with its parent; TOG + * made it impossible for a window to have a cursor without + * an optional record. + */ + if (pWin->optional->cursor) + { + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = FALSE; + } + else + pWin->cursorIsNone = TRUE; +/* FIXME + There is an error when disposing ClientResources on Agent exit + this xfree is not valid in some window at exit +*/ + + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +DrawLogo(WindowPtr pWin) +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.X.original new file mode 100644 index 000000000..c060f4a23 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.X.original @@ -0,0 +1,3853 @@ +/* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.12 2005/07/03 08:53:38 daniels Exp $ */ +/* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */ +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* $XFree86: xc/programs/Xserver/dix/window.c,v 3.36 2003/11/14 23:52:50 torrey Exp $ */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "dixevents.h" +#include "globals.h" + +#ifdef XAPPGROUP +#include +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include +#endif + +/****** + * Window stuff for server + * + * CreateRootWindow, CreateWindow, ChangeWindowAttributes, + * GetWindowAttributes, DeleteWindow, DestroySubWindows, + * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, + * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, + * + ******/ + +static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11}; +static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88}; + +int screenIsSaved = SCREEN_SAVER_OFF; + +ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; + +#if 0 +extern void DeleteWindowFromAnyEvents(); +extern Mask EventMaskForClient(); +extern void WindowHasNewCursor(); +extern void RecalculateDeliverableEvents(); +#endif + +static Bool TileScreenSaver(int i, int kind); + + +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +#define BOXES_OVERLAP(b1, b2) \ + (!( ((b1)->x2 <= (b2)->x1) || \ + ( ((b1)->x1 >= (b2)->x2)) || \ + ( ((b1)->y2 <= (b2)->y1)) || \ + ( ((b1)->y1 >= (b2)->y2)) ) ) + +#define RedirectSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask) + +#define SubSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask) + +#define StrSend(pWin) \ + ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask) + +#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) + + +int numSaveUndersViewable = 0; +int deltaSaveUndersViewable = 0; + +#ifdef DEBUG +/****** + * PrintWindowTree + * For debugging only + ******/ + +int +PrintChildren(WindowPtr p1, int indent) +{ + WindowPtr p2; + int i; + + while (p1) + { + p2 = p1->firstChild; + for (i=0; idrawable.id); + miPrintRegion(&p1->clipList); + PrintChildren(p2, indent+4); + p1 = p1->nextSib; + } +} + +PrintWindowTree() +{ + int i; + WindowPtr pWin, p1; + + for (i=0; iclipList); + p1 = pWin->firstChild; + PrintChildren(p1, 4); + } +} +#endif + +int +TraverseTree(register WindowPtr pWin, VisitWindowProcPtr func, pointer data) +{ + register int result; + register WindowPtr pChild; + + if (!(pChild = pWin)) + return(WT_NOMATCH); + while (1) + { + result = (* func)(pChild, data); + if (result == WT_STOPWALKING) + return(WT_STOPWALKING); + if ((result == WT_WALKCHILDREN) && pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + return(WT_NOMATCH); +} + +/***** + * WalkTree + * Walk the window tree, for SCREEN, preforming FUNC(pWin, data) on + * each window. If FUNC returns WT_WALKCHILDREN, traverse the children, + * if it returns WT_DONTWALKCHILDREN, dont. If it returns WT_STOPWALKING + * exit WalkTree. Does depth-first traverse. + *****/ + +int +WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data) +{ + return(TraverseTree(WindowTable[pScreen->myNum], func, data)); +} + +/* hack for forcing backing store on all windows */ +int defaultBackingStore = NotUseful; +/* hack to force no backing store */ +Bool disableBackingStore = FALSE; +Bool enableBackingStore = FALSE; +/* hack to force no save unders */ +Bool disableSaveUnders = FALSE; + +static void +SetWindowToDefaults(register WindowPtr pWin) +{ + pWin->prevSib = NullWindow; + pWin->firstChild = NullWindow; + pWin->lastChild = NullWindow; + + pWin->valdata = (ValidatePtr)NULL; + pWin->optional = (WindowOptPtr)NULL; + pWin->cursorIsNone = TRUE; + + pWin->backingStore = NotUseful; + pWin->DIXsaveUnder = FALSE; + pWin->backStorage = (pointer) NULL; + + pWin->mapped = FALSE; /* off */ + pWin->realized = FALSE; /* off */ + pWin->viewable = FALSE; + pWin->visibility = VisibilityNotViewable; + pWin->overrideRedirect = FALSE; + pWin->saveUnder = FALSE; + + pWin->bitGravity = ForgetGravity; + pWin->winGravity = NorthWestGravity; + + pWin->eventMask = 0; + pWin->deliverableEvents = 0; + pWin->dontPropagate = 0; + pWin->forcedBS = FALSE; +#ifdef NEED_DBE_BUF_BITS + pWin->srcBuffer = DBE_FRONT_BUFFER; + pWin->dstBuffer = DBE_FRONT_BUFFER; +#endif +#ifdef COMPOSITE + pWin->redirectDraw = 0; +#endif +} + +static void +MakeRootTile(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + GCPtr pGC; + unsigned char back[128]; + int len = BitmapBytePad(sizeof(long)); + register unsigned char *from, *to; + register int i, j; + + pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4, + pScreen->rootDepth); + + pWin->backgroundState = BackgroundPixmap; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pWin->background.pixmap || !pGC) + FatalError("could not create root tile"); + + { + CARD32 attributes[2]; + + attributes[0] = pScreen->whitePixel; + attributes[1] = pScreen->blackPixel; + + (void)ChangeGC(pGC, GCForeground | GCBackground, attributes); + } + + ValidateGC((DrawablePtr)pWin->background.pixmap, pGC); + + from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb; + to = back; + + for (i = 4; i > 0; i--, from++) + for (j = len; j > 0; j--) + *to++ = *from; + + if (blackRoot) + bzero(back, sizeof(back)); + + (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1, + 0, 0, len, 4, 0, XYBitmap, (char *)back); + + FreeScratchGC(pGC); + +} + +WindowPtr +AllocateWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + register char *ptr; + register DevUnion *ppriv; + register unsigned *sizes; + register unsigned size; + register int i; + + pWin = (WindowPtr)xalloc(pScreen->totalWindowSize); + if (pWin) + { + ppriv = (DevUnion *)(pWin + 1); + pWin->devPrivates = ppriv; + sizes = pScreen->WindowPrivateSizes; + ptr = (char *)(ppriv + pScreen->WindowPrivateLen); + for (i = pScreen->WindowPrivateLen; --i >= 0; ppriv++, sizes++) + { + if ( (size = *sizes) ) + { + ppriv->ptr = (pointer)ptr; + ptr += size; + } + else + ppriv->ptr = (pointer)NULL; + } + } + return pWin; +} + +/***** + * CreateRootWindow + * Makes a window at initialization time for specified screen + *****/ + +Bool +CreateRootWindow(ScreenPtr pScreen) +{ + WindowPtr pWin; + BoxRec box; + PixmapFormatRec *format; + + pWin = AllocateWindow(pScreen); + if (!pWin) + return FALSE; + + savedScreenInfo[pScreen->myNum].pWindow = NULL; + savedScreenInfo[pScreen->myNum].wid = FakeClientID(0); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + screenIsSaved = SCREEN_SAVER_OFF; + + WindowTable[pScreen->myNum] = pWin; + + pWin->drawable.pScreen = pScreen; + pWin->drawable.type = DRAWABLE_WINDOW; + + pWin->drawable.depth = pScreen->rootDepth; + for (format = screenInfo.formats; + format->depth != pScreen->rootDepth; + format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->parent = NullWindow; + SetWindowToDefaults(pWin); + + pWin->optional = (WindowOptRec *) xalloc (sizeof (WindowOptRec)); + if (!pWin->optional) + return FALSE; + + pWin->optional->dontPropagateMask = 0; + pWin->optional->otherEventMasks = 0; + pWin->optional->otherClients = NULL; + pWin->optional->passiveGrabs = NULL; + pWin->optional->userProps = NULL; + pWin->optional->backingBitPlanes = ~0L; + pWin->optional->backingPixel = 0; +#ifdef SHAPE + pWin->optional->boundingShape = NULL; + pWin->optional->clipShape = NULL; + pWin->optional->inputShape = NULL; +#endif +#ifdef XINPUT + pWin->optional->inputMasks = NULL; +#endif + pWin->optional->colormap = pScreen->defColormap; + pWin->optional->visual = pScreen->rootVisual; + + pWin->nextSib = NullWindow; + + pWin->drawable.id = FakeClientID(0); + + pWin->origin.x = pWin->origin.y = 0; + pWin->drawable.height = pScreen->height; + pWin->drawable.width = pScreen->width; + pWin->drawable.x = pWin->drawable.y = 0; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderSize, &box, 1); + REGION_INIT(pScreen, &pWin->borderClip, &box, 1); + + pWin->drawable.class = InputOutput; + pWin->optional->visual = pScreen->rootVisual; + + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = pScreen->whitePixel; + + pWin->borderIsPixel = TRUE; + pWin->border.pixel = pScreen->blackPixel; + pWin->borderWidth = 0; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (pointer)pWin)) + return FALSE; + + if (disableBackingStore) + pScreen->backingStoreSupport = NotUseful; + if (enableBackingStore) + pScreen->backingStoreSupport = Always; + +#ifdef DO_SAVE_UNDERS + if ((pScreen->backingStoreSupport != NotUseful) && + (pScreen->saveUnderSupport == NotUseful)) + { + /* + * If the screen has backing-store but no save-unders, let the + * clients know we can support save-unders using backing-store. + */ + pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; + } +#endif /* DO_SAVE_UNDERS */ + + if (disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + + return TRUE; +} + +void +InitRootWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!(*pScreen->CreateWindow)(pWin)) + return; /* XXX */ + (*pScreen->PositionWindow)(pWin, 0, 0); + + pWin->cursorIsNone = FALSE; + pWin->optional->cursor = rootCursor; + rootCursor->refcnt++; + MakeRootTile(pWin); + pWin->backingStore = defaultBackingStore; + pWin->forcedBS = (defaultBackingStore != NotUseful); + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, + CWBackPixmap|CWBorderPixel|CWCursor|CWBackingStore); + + MapWindow(pWin, serverClient); +} + +/* Set the region to the intersection of the rectangle and the + * window's winSize. The window is typically the parent of the + * window from which the region came. + */ + +void +ClippedRegionFromBox(register WindowPtr pWin, RegionPtr Rgn, + register int x, register int y, + register int w, register int h) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + BoxRec box; + + box = *(REGION_EXTENTS(pScreen, &pWin->winSize)); + /* we do these calculations to avoid overflows */ + if (x > box.x1) + box.x1 = x; + if (y > box.y1) + box.y1 = y; + x += w; + if (x < box.x2) + box.x2 = x; + y += h; + if (y < box.y2) + box.y2 = y; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + REGION_RESET(pScreen, Rgn, &box); + REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize); +} + +WindowPtr +RealChildHead(register WindowPtr pWin) +{ + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow (pWin->drawable.pScreen->myNum))) + return (pWin->firstChild); + else + return (NullWindow); +} + +/***** + * CreateWindow + * Makes a window in response to client request + *****/ + +WindowPtr +CreateWindow(Window wid, register WindowPtr pParent, int x, int y, unsigned w, + unsigned h, unsigned bw, unsigned class, register Mask vmask, XID *vlist, + int depth, ClientPtr client, VisualID visual, int *error) +{ + register WindowPtr pWin; + WindowPtr pHead; + register ScreenPtr pScreen; + xEvent event; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + PixmapFormatRec *format; + register WindowOptPtr ancwopt; + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + *error = BadValue; + client->errorValue = class; + return NullWindow; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + { + *error = BadMatch; + return NullWindow; + } + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + { + *error = BadMatch; + return NullWindow; + } + + pScreen = pParent->drawable.pScreen; + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) { +#ifdef XAPPGROUP + VisualID ag_visual; + + if (client->appgroup && !pParent->parent && + (ag_visual = XagRootVisual (client))) + visual = ag_visual; + else +#endif + visual = ancwopt->visual; + } + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + { + *error = BadMatch; + return NullWindow; + } + } + + if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + *error = BadMatch; + return NullWindow; + } + + if (((vmask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + *error = BadMatch; + return NullWindow; + } + + pWin = AllocateWindow(pScreen); + if (!pWin) + { + *error = BadAlloc; + return NullWindow; + } + pWin->drawable = pParent->drawable; + pWin->drawable.depth = depth; + if (depth == pParent->drawable.depth) + pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel; + else + { + for (format = screenInfo.formats; format->depth != depth; format++) + ; + pWin->drawable.bitsPerPixel = format->bitsPerPixel; + } + if (class == InputOnly) + pWin->drawable.type = (short) UNDRAWABLE_WINDOW; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pWin->drawable.id = wid; + pWin->drawable.class = class; + + pWin->parent = pParent; + SetWindowToDefaults(pWin); + + if (visual != ancwopt->visual) + { + if (!MakeWindowOptional (pWin)) + { + xfree (pWin); + *error = BadAlloc; + return NullWindow; + } + pWin->optional->visual = visual; + pWin->optional->colormap = None; + } + + pWin->borderWidth = bw; +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows; + * they make it too easy to steal window contents + */ + if (client->trustLevel != XSecurityClientTrusted) + { + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = 0; + } + else +#endif + pWin->backgroundState = None; + + pWin->borderIsPixel = pParent->borderIsPixel; + pWin->border = pParent->border; + if (pWin->borderIsPixel == FALSE) + pWin->border.pixmap->refcnt++; + + pWin->origin.x = x + (int)bw; + pWin->origin.y = y + (int)bw; + pWin->drawable.width = w; + pWin->drawable.height = h; + pWin->drawable.x = pParent->drawable.x + x + (int)bw; + pWin->drawable.y = pParent->drawable.y + y + (int)bw; + + /* set up clip list correctly for unobscured WindowPtr */ + REGION_NULL(pScreen, &pWin->clipList); + REGION_NULL(pScreen, &pWin->borderClip); + REGION_NULL(pScreen, &pWin->winSize); + REGION_NULL(pScreen, &pWin->borderSize); + + pHead = RealChildHead(pParent); + if (pHead) + { + pWin->nextSib = pHead->nextSib; + if (pHead->nextSib) + pHead->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pHead->nextSib = pWin; + pWin->prevSib = pHead; + } + else + { + pWin->nextSib = pParent->firstChild; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + SetWinSize (pWin); + SetBorderSize (pWin); + + /* We SHOULD check for an error value here XXX */ + if (!(*pScreen->CreateWindow)(pWin)) + { + *error = BadAlloc; + DeleteWindow(pWin, None); + return NullWindow; + } + /* We SHOULD check for an error value here XXX */ + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + + if (!(vmask & CWEventMask)) + RecalculateDeliverableEvents(pWin); + + if (vmask) + *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient (pWin)); + else + *error = Success; + + if (*error != Success) + { + DeleteWindow(pWin, None); + return NullWindow; + } + if (!(vmask & CWBackingStore) && (defaultBackingStore != NotUseful)) + { + XID value = defaultBackingStore; + (void)ChangeWindowAttributes(pWin, CWBackingStore, &value, wClient (pWin)); + pWin->forcedBS = TRUE; + } + + if (SubSend(pParent)) + { + event.u.u.type = CreateNotify; + event.u.createNotify.window = wid; + event.u.createNotify.parent = pParent->drawable.id; + event.u.createNotify.x = x; + event.u.createNotify.y = y; + event.u.createNotify.width = w; + event.u.createNotify.height = h; + event.u.createNotify.borderWidth = bw; + event.u.createNotify.override = pWin->overrideRedirect; + DeliverEvents(pParent, &event, 1, NullWindow); + } + return pWin; +} + +static void +FreeWindowResources(register WindowPtr pWin) +{ + register ScreenPtr pScreen = pWin->drawable.pScreen; + + DeleteWindowFromAnySaveSet(pWin); + DeleteWindowFromAnySelections(pWin); + DeleteWindowFromAnyEvents(pWin, TRUE); + REGION_UNINIT(pScreen, &pWin->clipList); + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_UNINIT(pScreen, &pWin->borderClip); + REGION_UNINIT(pScreen, &pWin->borderSize); +#ifdef SHAPE + if (wBoundingShape (pWin)) + REGION_DESTROY(pScreen, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_DESTROY(pScreen, wClipShape (pWin)); + if (wInputShape (pWin)) + REGION_DESTROY(pScreen, wInputShape (pWin)); +#endif + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + + DeleteAllWindowProperties(pWin); + /* We SHOULD check for an error value here XXX */ + (*pScreen->DestroyWindow)(pWin); + DisposeWindowOptional (pWin); +} + +static void +CrushTree(WindowPtr pWin) +{ + register WindowPtr pChild, pSib, pParent; + UnrealizeWindowProcPtr UnrealizeWindow; + xEvent event; + + if (!(pChild = pWin->firstChild)) + return; + UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow; + while (1) + { + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (1) + { + pParent = pChild->parent; + if (SubStrSend(pChild, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pChild->drawable.id; + DeliverEvents(pChild, &event, 1, NullWindow); + } + FreeResource(pChild->drawable.id, RT_WINDOW); + pSib = pChild->nextSib; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder && pChild->viewable) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->realized) + { + pChild->realized = FALSE; + (*UnrealizeWindow)(pChild); + } + FreeWindowResources(pChild); + xfree(pChild); + if ( (pChild = pSib) ) + break; + pChild = pParent; + pChild->firstChild = NullWindow; + pChild->lastChild = NullWindow; + if (pChild == pWin) + return; + } + } +} + +/***** + * DeleteWindow + * Deletes child of window then window itself + * If wid is None, don't send any events + *****/ + +int +DeleteWindow(pointer value, XID wid) + { + register WindowPtr pParent; + register WindowPtr pWin = (WindowPtr)value; + xEvent event; + + UnmapWindow(pWin, FALSE); + + CrushTree(pWin); + + pParent = pWin->parent; + if (wid && pParent && SubStrSend(pWin, pParent)) + { + event.u.u.type = DestroyNotify; + event.u.destroyNotify.window = pWin->drawable.id; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + FreeWindowResources(pWin); + if (pParent) + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + } + xfree(pWin); + return Success; +} + +void +DestroySubwindows(register WindowPtr pWin, ClientPtr client) +{ + /* XXX + * The protocol is quite clear that each window should be + * destroyed in turn, however, unmapping all of the first + * eliminates most of the calls to ValidateTree. So, + * this implementation is incorrect in that all of the + * UnmapNotifies occur before all of the DestroyNotifies. + * If you care, simply delete the call to UnmapSubwindows. + */ + UnmapSubwindows(pWin); + while (pWin->lastChild) + FreeResource(pWin->lastChild->drawable.id, RT_NONE); +} + +#define DeviceEventMasks (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + +/***** + * ChangeWindowAttributes + * + * The value-mask specifies which attributes are to be changed; the + * value-list contains one value for each one bit in the mask, from least + * to most significant bit in the mask. + *****/ + +int +ChangeWindowAttributes(register WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) +{ + register Mask index2; + register XID *pVlist; + PixmapPtr pPixmap; + Pixmap pixID; + CursorPtr pCursor, pOldCursor; + Cursor cursorID; + WindowPtr pChild; + Colormap cmap; + ColormapPtr pCmap; + xEvent xE; + int result; + register ScreenPtr pScreen; + Mask vmaskCopy = 0; + register Mask tmask; + unsigned int val; + int error; + Bool checkOptional = FALSE; + Bool borderRelative = FALSE; + WindowPtr pLayerWin; + + if ((pWin->drawable.class == InputOnly) && (vmask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + error = Success; + pScreen = pWin->drawable.pScreen; + pVlist = vlist; + tmask = vmask; + while (tmask) + { + index2 = (Mask) lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + pVlist++; + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pixID == None) + { +#ifdef XCSECURITY + /* can't let untrusted clients have background None windows */ + if (client->trustLevel == XSecurityClientTrusted) + { +#endif + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = None; +#ifdef XCSECURITY + } + else + { /* didn't change the background to None, so don't tell ddx */ + index2 = 0; + } +#endif + } + else if (pixID == ParentRelative) + { + if (pWin->parent && + pWin->drawable.depth != pWin->parent->drawable.depth) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + if (!pWin->parent) + MakeRootTile(pWin); + else + pWin->backgroundState = ParentRelative; + borderRelative = TRUE; + /* Note that the parent's backgroundTile's refcnt is NOT + * incremented. */ + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap != (PixmapPtr) NULL) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + if (pWin->backgroundState == ParentRelative) + borderRelative = TRUE; + if (pWin->backgroundState == BackgroundPixmap) + (*pScreen->DestroyPixmap)(pWin->background.pixmap); + pWin->backgroundState = BackgroundPixel; + pWin->background.pixel = (CARD32 ) *pVlist; + /* background pixel overrides background pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBackPixmap; + pVlist++; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + pVlist++; + if (pixID == CopyFromParent) + { + if (!pWin->parent || + (pWin->drawable.depth != pWin->parent->drawable.depth)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->border = pWin->parent->border; + if ((pWin->borderIsPixel = pWin->parent->borderIsPixel) == TRUE) + { + index2 = CWBorderPixel; + } + else + { + pWin->parent->border.pixmap->refcnt++; + } + } + else + { + pPixmap = (PixmapPtr)SecurityLookupIDByType(client, pixID, + RT_PIXMAP, SecurityReadAccess); + if (pPixmap) + { + if ((pPixmap->drawable.depth != pWin->drawable.depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + error = BadMatch; + goto PatchUp; + } + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pPixmap; + pPixmap->refcnt++; + } + else + { + error = BadPixmap; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + if (pWin->borderIsPixel == FALSE) + (*pScreen->DestroyPixmap)(pWin->border.pixmap); + pWin->borderIsPixel = TRUE; + pWin->border.pixel = (CARD32) *pVlist; + /* border pixel overrides border pixmap, + so don't let the ddx layer see both bits */ + vmaskCopy &= ~CWBorderPixmap; + pVlist++; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->bitGravity = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + pVlist++; + if (val > StaticGravity) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->winGravity = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + pVlist++; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->backingStore = val; + pWin->forcedBS = FALSE; + break; + case CWBackingPlanes: + if (pWin->optional || ((CARD32)*pVlist != (CARD32)~0L)) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingBitPlanes = (CARD32) *pVlist; + if ((CARD32)*pVlist == (CARD32)~0L) + checkOptional = TRUE; + } + pVlist++; + break; + case CWBackingPixel: + if (pWin->optional || (CARD32) *pVlist) { + if (!pWin->optional && !MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + pWin->optional->backingPixel = (CARD32) *pVlist; + if (!*pVlist) + checkOptional = TRUE; + } + pVlist++; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } +#ifdef DO_SAVE_UNDERS + if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && + DO_SAVE_UNDERS(pWin)) + { + /* + * Re-check all siblings and inferiors for obscurity or + * exposition (hee hee). + */ + if (pWin->saveUnder) + deltaSaveUndersViewable--; + else + deltaSaveUndersViewable++; + pWin->saveUnder = val; + + if (pWin->firstChild) + { + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, + pWin->nextSib); + } + else + { + if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) + (*pScreen->PostChangeSaveUnder)(pWin, + pWin->nextSib); + } + } + else + { + /* If we're changing the saveUnder attribute of the root + * window, all we do is set pWin->saveUnder so that + * GetWindowAttributes returns the right value. We don't + * do the "normal" save-under processing (as above). + * Hope that doesn't cause any problems. + */ + pWin->saveUnder = val; + } +#else + pWin->saveUnder = val; +#endif /* DO_SAVE_UNDERS */ + break; + case CWEventMask: + result = EventSelectForWindow(pWin, client, (Mask )*pVlist); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWDontPropagate: + result = EventSuppressForWindow(pWin, client, (Mask )*pVlist, + &checkOptional); + if (result) + { + error = result; + goto PatchUp; + } + pVlist++; + break; + case CWOverrideRedirect: + val = (BOOL ) *pVlist; + pVlist++; + if ((val != xTrue) && (val != xFalse)) + { + error = BadValue; + client->errorValue = val; + goto PatchUp; + } + pWin->overrideRedirect = val; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + pVlist++; + if (cmap == CopyFromParent) + { +#ifdef XAPPGROUP + Colormap ag_colormap; + ClientPtr win_owner; + + /* + * win_owner == client for CreateWindow, other clients + * can ChangeWindowAttributes + */ + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + + if ( win_owner && win_owner->appgroup && + !pWin->parent->parent && + (ag_colormap = XagDefaultColormap (win_owner))) + cmap = ag_colormap; + else +#endif + if (pWin->parent && + (!pWin->optional || + pWin->optional->visual == wVisual (pWin->parent))) + { + cmap = wColormap (pWin->parent); + } + else + cmap = None; + } + if (cmap == None) + { + error = BadMatch; + goto PatchUp; + } + pCmap = (ColormapPtr)SecurityLookupIDByType(client, cmap, + RT_COLORMAP, SecurityReadAccess); + if (!pCmap) + { + error = BadColor; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != wVisual (pWin) || + pCmap->pScreen != pScreen) + { + error = BadMatch; + goto PatchUp; + } + if (cmap != wColormap (pWin)) + { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && cmap == wColormap (pWin->parent)) + checkOptional = TRUE; + + /* + * propagate the original colormap to any children + * inheriting it + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pWin->optional->colormap = cmap; + + /* + * check on any children now matching the new colormap + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional->colormap == cmap) + CheckWindowOptionalNeed (pChild); + } + + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pWin->drawable.id; + xE.u.colormap.colormap = cmap; + xE.u.colormap.new = xTrue; + xE.u.colormap.state = IsMapInstalled(cmap, pWin); + DeliverEvents(pWin, &xE, 1, NullWindow); + } + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + pVlist++; + /* + * install the new + */ + if ( cursorID == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr) None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, cursorID, + RT_CURSOR, SecurityReadAccess); + if (!pCursor) + { + error = BadCursor; + client->errorValue = cursorID; + goto PatchUp; + } + } + + if (pCursor != wCursor (pWin)) + { + /* + * patch up child windows so they don't lose cursors. + */ + + for (pChild = pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (!pChild->optional && !pChild->cursorIsNone && + !MakeWindowOptional (pChild)) + { + error = BadAlloc; + goto PatchUp; + } + } + + pOldCursor = 0; + if (pCursor == (CursorPtr) None) + { + pWin->cursorIsNone = TRUE; + if (pWin->optional) + { + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = (CursorPtr) None; + checkOptional = TRUE; + } + } else { + if (!pWin->optional) + { + if (!MakeWindowOptional (pWin)) + { + error = BadAlloc; + goto PatchUp; + } + } + else if (pWin->parent && pCursor == wCursor (pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; + pWin->optional->cursor = pCursor; + pCursor->refcnt++; + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor + */ + + for (pChild=pWin->firstChild; pChild; pChild=pChild->nextSib) + { + if (pChild->optional && + (pChild->optional->cursor == pCursor)) + CheckWindowOptionalNeed (pChild); + } + } + + if (pWin->realized) + WindowHasNewCursor( pWin); + + /* Can't free cursor until here - old cursor + * is needed in WindowHasNewCursor + */ + if (pOldCursor) + FreeCursor (pOldCursor, (Cursor)0); + } + break; + default: + error = BadValue; + client->errorValue = vmask; + goto PatchUp; + } + vmaskCopy |= index2; + } +PatchUp: + if (checkOptional) + CheckWindowOptionalNeed (pWin); + + /* We SHOULD check for an error value here XXX */ + (*pScreen->ChangeWindowAttributes)(pWin, vmaskCopy); + + /* + If the border contents have changed, redraw the border. + Note that this has to be done AFTER pScreen->ChangeWindowAttributes + for the tile to be rotated, and the correct function selected. + */ + if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative) + && pWin->viewable && HasBorder (pWin)) + { + RegionRec exposed; + + REGION_NULL(pScreen, &exposed); + REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize); + (*pWin->drawable.pScreen->PaintWindowBorder)(pWin, &exposed, PW_BORDER); + REGION_UNINIT(pScreen, &exposed); + } + return error; +} + + +/***** + * GetWindowAttributes + * Notice that this is different than ChangeWindowAttributes + *****/ + +void +GetWindowAttributes(register WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply *wa) +{ + wa->type = X_Reply; + wa->bitGravity = pWin->bitGravity; + wa->winGravity = pWin->winGravity; + if (pWin->forcedBS && pWin->backingStore != Always) + wa->backingStore = NotUseful; + else + wa->backingStore = pWin->backingStore; + wa->length = (sizeof(xGetWindowAttributesReply) - + sizeof(xGenericReply)) >> 2; + wa->sequenceNumber = client->sequence; + wa->backingBitPlanes = wBackingBitPlanes (pWin); + wa->backingPixel = wBackingPixel (pWin); + wa->saveUnder = (BOOL)pWin->saveUnder; + wa->override = pWin->overrideRedirect; + if (!pWin->mapped) + wa->mapState = IsUnmapped; + else if (pWin->realized) + wa->mapState = IsViewable; + else + wa->mapState = IsUnviewable; + + wa->colormap = wColormap (pWin); + wa->mapInstalled = (wa->colormap == None) ? xFalse + : IsMapInstalled(wa->colormap, pWin); + + wa->yourEventMask = EventMaskForClient(pWin, client); + wa->allEventMasks = pWin->eventMask | wOtherEventMasks (pWin); + wa->doNotPropagateMask = wDontPropagateMask (pWin); + wa->class = pWin->drawable.class; + wa->visualID = wVisual (pWin); +} + + +WindowPtr +MoveWindowInStack(register WindowPtr pWin, register WindowPtr pNextSib) +{ + register WindowPtr pParent = pWin->parent; + WindowPtr pFirstChange = pWin; /* highest window where list changes */ + + if (pWin->nextSib != pNextSib) + { + WindowPtr pOldNextSib = pWin->nextSib; + + if (!pNextSib) /* move to bottom */ + { + if (pParent->firstChild == pWin) + pParent->firstChild = pWin->nextSib; + /* if (pWin->nextSib) */ /* is always True: pNextSib == NULL + * and pWin->nextSib != pNextSib + * therefore pWin->nextSib != NULL */ + pFirstChange = pWin->nextSib; + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pParent->lastChild->nextSib = pWin; + pWin->prevSib = pParent->lastChild; + pWin->nextSib = NullWindow; + pParent->lastChild = pWin; + } + else if (pParent->firstChild == pNextSib) /* move to top */ + { + pFirstChange = pWin; + if (pParent->lastChild == pWin) + pParent->lastChild = pWin->prevSib; + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pParent->firstChild; + pWin->prevSib = (WindowPtr ) NULL; + pNextSib->prevSib = pWin; + pParent->firstChild = pWin; + } + else /* move in middle of list */ + { + WindowPtr pOldNext = pWin->nextSib; + + pFirstChange = NullWindow; + if (pParent->firstChild == pWin) + pFirstChange = pParent->firstChild = pWin->nextSib; + if (pParent->lastChild == pWin) { + pFirstChange = pWin; + pParent->lastChild = pWin->prevSib; + } + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + pWin->nextSib = pNextSib; + pWin->prevSib = pNextSib->prevSib; + if (pNextSib->prevSib) + pNextSib->prevSib->nextSib = pWin; + pNextSib->prevSib = pWin; + if (!pFirstChange) { /* do we know it yet? */ + pFirstChange = pParent->firstChild; /* no, search from top */ + while ((pFirstChange != pWin) && (pFirstChange != pOldNext)) + pFirstChange = pFirstChange->nextSib; + } + } + if(pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pOldNextSib); + } + +#ifdef ROOTLESS + /* + * In rootless mode we can't optimize away window restacks. + * There may be non-X windows around, so even if the window + * is in the correct position from X's point of view, + * the underlying window system may want to reorder it. + */ + else if (pWin->drawable.pScreen->RestackWindow) + (*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib); +#endif + + return( pFirstChange ); +} + +RegionPtr +CreateUnclippedWinSize (register WindowPtr pWin) +{ + RegionPtr pRgn; + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + (int) pWin->drawable.width; + box.y2 = pWin->drawable.y + (int) pWin->drawable.height; + pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, pRgn, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); + } +#endif + return pRgn; +} + +void +SetWinSize (register WindowPtr pWin) +{ +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x; + box.y1 = pWin->drawable.y; + box.x2 = pWin->drawable.x + pWin->drawable.width; + box.y2 = pWin->drawable.y + pWin->drawable.height; + REGION_RESET (pScreen, &pWin->winSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->winSize, + pWin->drawable.x, pWin->drawable.y, + (int)pWin->drawable.width, + (int)pWin->drawable.height); +#ifdef SHAPE + if (wBoundingShape (pWin) || wClipShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x, + - pWin->drawable.y); + if (wBoundingShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wBoundingShape (pWin)); + if (wClipShape (pWin)) + REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize, + wClipShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, + pWin->drawable.y); + } +#endif +} + +void +SetBorderSize (register WindowPtr pWin) +{ + int bw; + + if (HasBorder (pWin)) { + bw = wBorderWidth (pWin); +#ifdef COMPOSITE + if (pWin->redirectDraw) + { + BoxRec box; + + box.x1 = pWin->drawable.x - bw; + box.y1 = pWin->drawable.y - bw; + box.x2 = pWin->drawable.x + pWin->drawable.width + bw; + box.y2 = pWin->drawable.y + pWin->drawable.height + bw; + REGION_RESET (pScreen, &pWin->borderSize, &box); + } + else +#endif + ClippedRegionFromBox(pWin->parent, &pWin->borderSize, + pWin->drawable.x - bw, pWin->drawable.y - bw, + (int)(pWin->drawable.width + (bw<<1)), + (int)(pWin->drawable.height + (bw<<1))); +#ifdef SHAPE + if (wBoundingShape (pWin)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x, + - pWin->drawable.y); + REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize, + wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x, + pWin->drawable.y); + REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, + &pWin->winSize); + } +#endif + } else { + REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, + &pWin->winSize); + } +} + +/** + * + * \param x,y new window position + * \param oldx,oldy old window position + * \param destx,desty position relative to gravity + */ + +void +GravityTranslate (register int x, register int y, int oldx, int oldy, + int dw, int dh, unsigned gravity, + register int *destx, register int *desty) +{ + switch (gravity) { + case NorthGravity: + *destx = x + dw / 2; + *desty = y; + break; + case NorthEastGravity: + *destx = x + dw; + *desty = y; + break; + case WestGravity: + *destx = x; + *desty = y + dh / 2; + break; + case CenterGravity: + *destx = x + dw / 2; + *desty = y + dh / 2; + break; + case EastGravity: + *destx = x + dw; + *desty = y + dh / 2; + break; + case SouthWestGravity: + *destx = x; + *desty = y + dh; + break; + case SouthGravity: + *destx = x + dw / 2; + *desty = y + dh; + break; + case SouthEastGravity: + *destx = x + dw; + *desty = y + dh; + break; + case StaticGravity: + *destx = oldx; + *desty = oldy; + break; + default: + *destx = x; + *desty = y; + break; + } +} + +/* XXX need to retile border on each window with ParentRelative origin */ +void +ResizeChildrenWinSize(register WindowPtr pWin, int dx, int dy, int dw, int dh) +{ + register ScreenPtr pScreen; + register WindowPtr pSib, pChild; + Bool resized = (dw || dh); + + pScreen = pWin->drawable.pScreen; + + for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) + { + if (resized && (pSib->winGravity > NorthWestGravity)) + { + int cwsx, cwsy; + + cwsx = pSib->origin.x; + cwsy = pSib->origin.y; + GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh, + pSib->winGravity, &cwsx, &cwsy); + if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) + { + xEvent event; + + event.u.u.type = GravityNotify; + event.u.gravity.window = pSib->drawable.id; + event.u.gravity.x = cwsx - wBorderWidth (pSib); + event.u.gravity.y = cwsy - wBorderWidth (pSib); + DeliverEvents (pSib, &event, 1, NullWindow); + pSib->origin.x = cwsx; + pSib->origin.y = cwsy; + } + } + pSib->drawable.x = pWin->drawable.x + pSib->origin.x; + pSib->drawable.y = pWin->drawable.y + pSib->origin.y; + SetWinSize (pSib); + SetBorderSize (pSib); + (*pScreen->PositionWindow)(pSib, pSib->drawable.x, pSib->drawable.y); + + if ( (pChild = pSib->firstChild) ) + { + while (1) + { + pChild->drawable.x = pChild->parent->drawable.x + + pChild->origin.x; + pChild->drawable.y = pChild->parent->drawable.y + + pChild->origin.y; + SetWinSize (pChild); + SetBorderSize (pChild); + (*pScreen->PositionWindow)(pChild, + pChild->drawable.x, pChild->drawable.y); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + while (!pChild->nextSib && (pChild != pSib)) + pChild = pChild->parent; + if (pChild == pSib) + break; + pChild = pChild->nextSib; + } + } + } +} + +#define GET_INT16(m, f) \ + if (m & mask) \ + { \ + f = (INT16) *pVlist;\ + pVlist++; \ + } +#define GET_CARD16(m, f) \ + if (m & mask) \ + { \ + f = (CARD16) *pVlist;\ + pVlist++;\ + } + +#define GET_CARD8(m, f) \ + if (m & mask) \ + { \ + f = (CARD8) *pVlist;\ + pVlist++;\ + } + +#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight)) + +#define IllegalInputOnlyConfigureMask (CWBorderWidth) + +/* + * IsSiblingAboveMe + * returns Above if pSib above pMe in stack or Below otherwise + */ + +static int +IsSiblingAboveMe( + register WindowPtr pMe, + register WindowPtr pSib) +{ + register WindowPtr pWin; + + pWin = pMe->parent->firstChild; + while (pWin) + { + if (pWin == pSib) + return(Above); + else if (pWin == pMe) + return(Below); + pWin = pWin->nextSib; + } + return(Below); +} + +static BoxPtr +WindowExtents( + register WindowPtr pWin, + register BoxPtr pBox) +{ + pBox->x1 = pWin->drawable.x - wBorderWidth (pWin); + pBox->y1 = pWin->drawable.y - wBorderWidth (pWin); + pBox->x2 = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + return(pBox); +} + +#ifdef SHAPE +#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) + +static RegionPtr +MakeBoundingRegion ( + register WindowPtr pWin, + BoxPtr pBox) +{ + RegionPtr pRgn; + ScreenPtr pScreen = pWin->drawable.pScreen; + + pRgn = REGION_CREATE(pScreen, pBox, 1); + if (wBoundingShape (pWin)) { + REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x, + -pWin->origin.y); + REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin)); + REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x, + pWin->origin.y); + } + return pRgn; +} + +static Bool +ShapeOverlap ( + WindowPtr pWin, + BoxPtr pWinBox, + WindowPtr pSib, + BoxPtr pSibBox) +{ + RegionPtr pWinRgn, pSibRgn; + register ScreenPtr pScreen; + Bool ret; + + if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib)) + return TRUE; + pScreen = pWin->drawable.pScreen; + pWinRgn = MakeBoundingRegion (pWin, pWinBox); + pSibRgn = MakeBoundingRegion (pSib, pSibBox); + REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn); + ret = REGION_NOTEMPTY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pWinRgn); + REGION_DESTROY(pScreen, pSibRgn); + return ret; +} +#endif + +static Bool +AnyWindowOverlapsMe( + WindowPtr pWin, + WindowPtr pHead, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +static Bool +IOverlapAnyWindow( + WindowPtr pWin, + register BoxPtr box) +{ + register WindowPtr pSib; + BoxRec sboxrec; + register BoxPtr sbox; + + for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) + { + if (pSib->mapped) + { + sbox = WindowExtents(pSib, &sboxrec); + if (BOXES_OVERLAP(sbox, box) +#ifdef SHAPE + && ShapeOverlap (pWin, box, pSib, sbox) +#endif + ) + return(TRUE); + } + } + return(FALSE); +} + +/* + * WhereDoIGoInTheStack() + * Given pWin and pSib and the relationshipe smode, return + * the window that pWin should go ABOVE. + * If a pSib is specified: + * Above: pWin is placed just above pSib + * Below: pWin is placed just below pSib + * TopIf: if pSib occludes pWin, then pWin is placed + * at the top of the stack + * BottomIf: if pWin occludes pSib, then pWin is + * placed at the bottom of the stack + * Opposite: if pSib occludes pWin, then pWin is placed at the + * top of the stack, else if pWin occludes pSib, then + * pWin is placed at the bottom of the stack + * + * If pSib is NULL: + * Above: pWin is placed at the top of the stack + * Below: pWin is placed at the bottom of the stack + * TopIf: if any sibling occludes pWin, then pWin is placed at + * the top of the stack + * BottomIf: if pWin occludes any sibline, then pWin is placed at + * the bottom of the stack + * Opposite: if any sibling occludes pWin, then pWin is placed at + * the top of the stack, else if pWin occludes any + * sibling, then pWin is placed at the bottom of the stack + * + */ + +static WindowPtr +WhereDoIGoInTheStack( + register WindowPtr pWin, + register WindowPtr pSib, + short x, + short y, + unsigned short w, + unsigned short h, + int smode) +{ + BoxRec box; + register ScreenPtr pScreen; + WindowPtr pHead, pFirst; + + if ((pWin == pWin->parent->firstChild) && + (pWin == pWin->parent->lastChild)) + return((WindowPtr ) NULL); + pHead = RealChildHead(pWin->parent); + pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild; + pScreen = pWin->drawable.pScreen; + box.x1 = x; + box.y1 = y; + box.x2 = x + (int)w; + box.y2 = y + (int)h; + switch (smode) + { + case Above: + if (pSib) + return(pSib); + else if (pWin == pFirst) + return(pWin->nextSib); + else + return(pFirst); + case Below: + if (pSib) + if (pSib->nextSib != pWin) + return(pSib->nextSib); + else + return(pWin->nextSib); + else + return NullWindow; + case TopIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Above) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return(pFirst); + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + return(pFirst); + else + return(pWin->nextSib); + case BottomIf: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if ((IsSiblingAboveMe(pWin, pSib) == Below) && + (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)) + return NullWindow; + else + return(pWin->nextSib); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return(pWin->nextSib); + case Opposite: + if ((!pWin->mapped || (pSib && !pSib->mapped)) && !permitOldBugs) + return(pWin->nextSib); + else if (pSib) + { + if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT) + { + if (IsSiblingAboveMe(pWin, pSib) == Above) + return(pFirst); + else + return NullWindow; + } + else + return(pWin->nextSib); + } + else if (AnyWindowOverlapsMe(pWin, pHead, &box)) + { + /* If I'm occluded, I can't possibly be the first child + * if (pWin == pWin->parent->firstChild) + * return pWin->nextSib; + */ + return(pFirst); + } + else if (IOverlapAnyWindow(pWin, &box)) + return NullWindow; + else + return pWin->nextSib; + default: + { + ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode ); + return pWin->nextSib; + } + } +} + +static void +ReflectStackChange( + register WindowPtr pWin, + register WindowPtr pSib, + VTKind kind) +{ +/* Note that pSib might be NULL */ + + Bool WasViewable = (Bool)pWin->viewable; + Bool anyMarked; + WindowPtr pFirstChange; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* if this is a root window, can't be restacked */ + if (!pWin->parent) + return; + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, + &pLayerWin); + if (pLayerWin != pWin) pFirstChange = pLayerWin; +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pWin->drawable.pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); + } + if (pWin->realized) + WindowsRestructured (); +} + +/***** + * ConfigureWindow + *****/ + +int +ConfigureWindow(register WindowPtr pWin, register Mask mask, XID *vlist, ClientPtr client) +{ +#define RESTACK_WIN 0 +#define MOVE_WIN 1 +#define RESIZE_WIN 2 +#define REBORDER_WIN 3 + register WindowPtr pSib = NullWindow; + register WindowPtr pParent = pWin->parent; + Window sibwid = 0; + Mask index2, tmask; + register XID *pVlist; + short x, y, beforeX, beforeY; + unsigned short w = pWin->drawable.width, + h = pWin->drawable.height, + bw = pWin->borderWidth; + int action, smode = Above; +#ifdef XAPPGROUP + ClientPtr win_owner; + ClientPtr ag_leader = NULL; +#endif + xEvent event; + + if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) + return(BadMatch); + + if ((mask & CWSibling) && !(mask & CWStackMode)) + return(BadMatch); + + pVlist = vlist; + + if (pParent) + { + x = pWin->drawable.x - pParent->drawable.x - (int)bw; + y = pWin->drawable.y - pParent->drawable.y - (int)bw; + } + else + { + x = pWin->drawable.x; + y = pWin->drawable.y; + } + beforeX = x; + beforeY = y; + action = RESTACK_WIN; + if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + action = MOVE_WIN; + } + /* or should be resized */ + else if (mask & (CWX | CWY | CWWidth | CWHeight)) + { + GET_INT16(CWX, x); + GET_INT16(CWY, y); + GET_CARD16(CWWidth, w); + GET_CARD16 (CWHeight, h); + if (!w || !h) + { + client->errorValue = 0; + return BadValue; + } + action = RESIZE_WIN; + } + tmask = mask & ~ChangeMask; + while (tmask) + { + index2 = (Mask)lowbit (tmask); + tmask &= ~index2; + switch (index2) + { + case CWBorderWidth: + GET_CARD16(CWBorderWidth, bw); + break; + case CWSibling: + sibwid = (Window ) *pVlist; + pVlist++; + pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid, + RT_WINDOW, SecurityReadAccess); + if (!pSib) + { + client->errorValue = sibwid; + return(BadWindow); + } + if (pSib->parent != pParent) + return(BadMatch); + if (pSib == pWin) + return(BadMatch); + break; + case CWStackMode: + GET_CARD8(CWStackMode, smode); + if ((smode != TopIf) && (smode != BottomIf) && + (smode != Opposite) && (smode != Above) && (smode != Below)) + { + client->errorValue = smode; + return(BadValue); + } + break; + default: + client->errorValue = mask; + return(BadValue); + } + } + /* root really can't be reconfigured, so just return */ + if (!pParent) + return Success; + + /* Figure out if the window should be moved. Doesnt + make the changes to the window if event sent */ + + if (mask & CWStackMode) + pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x, + pParent->drawable.y + y, + w + (bw << 1), h + (bw << 1), smode); + else + pSib = pWin->nextSib; + +#ifdef XAPPGROUP + win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = ConfigureRequest; + event.u.configureRequest.window = pWin->drawable.id; + if (mask & CWSibling) + event.u.configureRequest.sibling = sibwid; + else + event.u.configureRequest.sibling = None; + if (mask & CWStackMode) + event.u.u.detail = smode; + else + event.u.u.detail = Above; + event.u.configureRequest.x = x; + event.u.configureRequest.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureRequest.x += panoramiXdataPtr[0].x; + event.u.configureRequest.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureRequest.width = w; + event.u.configureRequest.height = h; + event.u.configureRequest.borderWidth = bw; + event.u.configureRequest.valueMask = mask; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.configureRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.configureRequest.parent = pParent->drawable.id; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + if (action == RESIZE_WIN) + { + Bool size_change = (w != pWin->drawable.width) + || (h != pWin->drawable.height); + if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask)) + { + xEvent eventT; + eventT.u.u.type = ResizeRequest; + eventT.u.resizeRequest.window = pWin->drawable.id; + eventT.u.resizeRequest.width = w; + eventT.u.resizeRequest.height = h; + if (MaybeDeliverEventsToClient(pWin, &eventT, 1, + ResizeRedirectMask, client) == 1) + { + /* if event is delivered, leave the actual size alone. */ + w = pWin->drawable.width; + h = pWin->drawable.height; + size_change = FALSE; + } + } + if (!size_change) + { + if (mask & (CWX | CWY)) + action = MOVE_WIN; + else if (mask & (CWStackMode | CWBorderWidth)) + action = RESTACK_WIN; + else /* really nothing to do */ + return(Success) ; + } + } + + if (action == RESIZE_WIN) + /* we've already checked whether there's really a size change */ + goto ActuallyDoSomething; + if ((mask & CWX) && (x != beforeX)) + goto ActuallyDoSomething; + if ((mask & CWY) && (y != beforeY)) + goto ActuallyDoSomething; + if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin))) + goto ActuallyDoSomething; + if (mask & CWStackMode) + { +#ifndef ROOTLESS + /* See above for why we always reorder in rootless mode. */ + if (pWin->nextSib != pSib) +#endif + goto ActuallyDoSomething; + } + return(Success); + +ActuallyDoSomething: + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = ConfigureNotify; + event.u.configureNotify.window = pWin->drawable.id; + if (pSib) + event.u.configureNotify.aboveSibling = pSib->drawable.id; + else + event.u.configureNotify.aboveSibling = None; + event.u.configureNotify.x = x; + event.u.configureNotify.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && (!pParent || !pParent->parent)) { + event.u.configureNotify.x += panoramiXdataPtr[0].x; + event.u.configureNotify.y += panoramiXdataPtr[0].y; + } +#endif + event.u.configureNotify.width = w; + event.u.configureNotify.height = h; + event.u.configureNotify.borderWidth = bw; + event.u.configureNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (mask & CWBorderWidth) + { + if (action == RESTACK_WIN) + { + action = MOVE_WIN; + pWin->borderWidth = bw; + } + else if ((action == MOVE_WIN) && + (beforeX + wBorderWidth (pWin) == x + (int)bw) && + (beforeY + wBorderWidth (pWin) == y + (int)bw)) + { + action = REBORDER_WIN; + (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw); + } + else + pWin->borderWidth = bw; + } + if (action == MOVE_WIN) + (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib, + (mask & CWBorderWidth) ? VTOther : VTMove); + else if (action == RESIZE_WIN) + (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + else if (mask & CWStackMode) + ReflectStackChange(pWin, pSib, VTOther); + + if (action != RESTACK_WIN) + CheckCursorConfinement(pWin); + return(Success); +#undef RESTACK_WIN +#undef MOVE_WIN +#undef RESIZE_WIN +#undef REBORDER_WIN +} + + +/****** + * + * CirculateWindow + * For RaiseLowest, raises the lowest mapped child (if any) that is + * obscured by another child to the top of the stack. For LowerHighest, + * lowers the highest mapped child (if any) that is obscuring another + * child to the bottom of the stack. Exposure processing is performed + * + ******/ + +int +CirculateWindow(WindowPtr pParent, int direction, ClientPtr client) +{ + register WindowPtr pWin, pHead, pFirst; + xEvent event; + BoxRec box; + + pHead = RealChildHead(pParent); + pFirst = pHead ? pHead->nextSib : pParent->firstChild; + if (direction == RaiseLowest) + { + for (pWin = pParent->lastChild; + (pWin != pHead) && + !(pWin->mapped && + AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box))); + pWin = pWin->prevSib) ; + if (pWin == pHead) + return Success; + } + else + { + for (pWin = pFirst; + pWin && + !(pWin->mapped && + IOverlapAnyWindow(pWin, WindowExtents(pWin, &box))); + pWin = pWin->nextSib) ; + if (!pWin) + return Success; + } + + event.u.circulate.window = pWin->drawable.id; + event.u.circulate.parent = pParent->drawable.id; + event.u.circulate.event = pParent->drawable.id; + if (direction == RaiseLowest) + event.u.circulate.place = PlaceOnTop; + else + event.u.circulate.place = PlaceOnBottom; + + if (RedirectSend(pParent)) + { + event.u.u.type = CirculateRequest; + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + event.u.u.type = CirculateNotify; + DeliverEvents(pWin, &event, 1, NullWindow); + ReflectStackChange(pWin, + (direction == RaiseLowest) ? pFirst : NullWindow, + VTStack); + + return(Success); +} + +static int +CompareWIDs( + WindowPtr pWin, + pointer value) /* must conform to VisitWindowProcPtr */ +{ + Window *wid = (Window *)value; + + if (pWin->drawable.id == *wid) + return(WT_STOPWALKING); + else + return(WT_WALKCHILDREN); +} + +/***** + * ReparentWindow + *****/ + +int +ReparentWindow(register WindowPtr pWin, register WindowPtr pParent, + int x, int y, ClientPtr client) +{ + WindowPtr pPrev, pPriorParent; + Bool WasMapped = (Bool)(pWin->mapped); + xEvent event; + int bw = wBorderWidth (pWin); + register ScreenPtr pScreen; + + pScreen = pWin->drawable.pScreen; + if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING) + return(BadMatch); + if (!MakeWindowOptional(pWin)) + return(BadAlloc); + + if (WasMapped) + UnmapWindow(pWin, FALSE); + + event.u.u.type = ReparentNotify; + event.u.reparent.window = pWin->drawable.id; + event.u.reparent.parent = pParent->drawable.id; + event.u.reparent.x = x; + event.u.reparent.y = y; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pParent->parent) { + event.u.reparent.x += panoramiXdataPtr[0].x; + event.u.reparent.y += panoramiXdataPtr[0].y; + } +#endif + event.u.reparent.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, pParent); + + /* take out of sibling chain */ + + pPriorParent = pPrev = pWin->parent; + if (pPrev->firstChild == pWin) + pPrev->firstChild = pWin->nextSib; + if (pPrev->lastChild == pWin) + pPrev->lastChild = pWin->prevSib; + + if (pWin->nextSib) + pWin->nextSib->prevSib = pWin->prevSib; + if (pWin->prevSib) + pWin->prevSib->nextSib = pWin->nextSib; + + /* insert at begining of pParent */ + pWin->parent = pParent; + pPrev = RealChildHead(pParent); + if (pPrev) + { + pWin->nextSib = pPrev->nextSib; + if (pPrev->nextSib) + pPrev->nextSib->prevSib = pWin; + else + pParent->lastChild = pWin; + pPrev->nextSib = pWin; + pWin->prevSib = pPrev; + } + else + { + pWin->nextSib = pParent->firstChild; + pWin->prevSib = NullWindow; + if (pParent->firstChild) + pParent->firstChild->prevSib = pWin; + else + pParent->lastChild = pWin; + pParent->firstChild = pWin; + } + + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.x = x + bw + pParent->drawable.x; + pWin->drawable.y = y + bw + pParent->drawable.y; + + /* clip to parent */ + SetWinSize (pWin); + SetBorderSize (pWin); + + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y); + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + CheckWindowOptionalNeed(pWin); + + if (WasMapped) + MapWindow(pWin, client); + RecalculateDeliverableEvents(pWin); + return(Success); +} + +static void +RealizeTree(WindowPtr pWin) +{ + register WindowPtr pChild; + RealizeWindowProcPtr Realize; + + Realize = pWin->drawable.pScreen->RealizeWindow; + pChild = pWin; + while (1) + { + if (pChild->mapped) + { + pChild->realized = TRUE; +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable++; +#endif + pChild->viewable = (pChild->drawable.class == InputOutput); + (* Realize)(pChild); + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * MapWindow + * If some other client has selected SubStructureReDirect on the parent + * and override-redirect is xFalse, then a MapRequest event is generated, + * but the window remains unmapped. Otherwise, the window is mapped and a + * MapNotify event is generated. + *****/ + +int +MapWindow(register WindowPtr pWin, ClientPtr client) +{ + register ScreenPtr pScreen; + + register WindowPtr pParent; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + if (pWin->mapped) + return(Success); + +#ifdef XCSECURITY + /* don't let an untrusted client map a child-of-trusted-window, InputOnly + * window; too easy to steal device input + */ + if ( (client->trustLevel != XSecurityClientTrusted) && + (pWin->drawable.class == InputOnly) && + (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) ) + return Success; +#endif + + pScreen = pWin->drawable.pScreen; + if ( (pParent = pWin->parent) ) + { + xEvent event; + Bool anyMarked; +#ifdef XAPPGROUP + ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; + ClientPtr ag_leader = XagLeader (win_owner); +#endif + + if ((!pWin->overrideRedirect) && + (RedirectSend(pParent) +#ifdef XAPPGROUP + || (win_owner->appgroup && ag_leader && + XagIsControlledRoot (client, pParent)) +#endif + )) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; +#ifdef XAPPGROUP + /* make sure if the ag_leader maps the window it goes to the wm */ + if (ag_leader && ag_leader != client && + XagIsControlledRoot (client, pParent)) { + event.u.mapRequest.parent = XagId (win_owner); + (void) TryClientEvents (ag_leader, &event, 1, + NoEventMask, NoEventMask, NullGrab); + return Success; + } +#endif + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + return(Success); + } + + pWin->mapped = TRUE; + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pParent->realized) + return(Success); + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, + &pLayerWin); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); + } + WindowsRestructured (); + } + else + { + RegionRec temp; + + pWin->mapped = TRUE; + pWin->realized = TRUE; /* for roots */ + pWin->viewable = pWin->drawable.class == InputOutput; + /* We SHOULD check for an error value here XXX */ + (*pScreen->RealizeWindow)(pWin); + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pWin, 0, 0); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap); + REGION_NULL(pScreen, &temp); + REGION_COPY(pScreen, &temp, &pWin->clipList); + (*pScreen->WindowExposures) (pWin, &temp, NullRegion); + REGION_UNINIT(pScreen, &temp); + } + + return(Success); +} + + +/***** + * MapSubwindows + * Performs a MapWindow all unmapped children of the window, in top + * to bottom stacking order. + *****/ + +void +MapSubwindows(register WindowPtr pParent, ClientPtr client) +{ + register WindowPtr pWin; + WindowPtr pFirstMapped = NullWindow; +#ifdef DO_SAVE_UNDERS + WindowPtr pFirstSaveUndered = NullWindow; +#endif + register ScreenPtr pScreen; + register Mask parentRedirect; + register Mask parentNotify; + xEvent event; + Bool anyMarked; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + + pScreen = pParent->drawable.pScreen; + parentRedirect = RedirectSend(pParent); + parentNotify = SubSend(pParent); + anyMarked = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (!pWin->mapped) + { + if (parentRedirect && !pWin->overrideRedirect) + { + event.u.u.type = MapRequest; + event.u.mapRequest.window = pWin->drawable.id; + event.u.mapRequest.parent = pParent->drawable.id; + + if (MaybeDeliverEventsToClient(pParent, &event, 1, + SubstructureRedirectMask, client) == 1) + continue; + } + + pWin->mapped = TRUE; + if (parentNotify || StrSend(pWin)) + { + event.u.u.type = MapNotify; + event.u.mapNotify.window = pWin->drawable.id; + event.u.mapNotify.override = pWin->overrideRedirect; + DeliverEvents(pWin, &event, 1, NullWindow); + } + + if (!pFirstMapped) + pFirstMapped = pWin; + if (pParent->realized) + { + RealizeTree(pWin); + if (pWin->viewable) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, + (WindowPtr *)NULL); +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = TRUE; + } +#endif /* DO_SAVE_UNDERS */ + } + } + } + } + + if (pFirstMapped) + { + pLayerWin = (*pScreen->GetLayerWindow)(pParent); + if (pLayerWin->parent != pParent) { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pLayerWin, + pLayerWin, + (WindowPtr *)NULL); + pFirstMapped = pLayerWin; + } + if (anyMarked) + { +#ifdef DO_SAVE_UNDERS + if (pLayerWin->parent != pParent) + { + if (dosave || (DO_SAVE_UNDERS(pLayerWin))) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, + pLayerWin); + } + } + else if (dosave) + { + dosave = FALSE; + for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) + { + if (DO_SAVE_UNDERS(pWin)) + { + dosave |= (*pScreen->ChangeSaveUnder)(pWin, + pWin->nextSib); + if (dosave && !pFirstSaveUndered) + pFirstSaveUndered = pWin; + } + } + } +#endif /* DO_SAVE_UNDERS */ + (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, + pFirstSaveUndered->nextSib); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, + VTMap); + WindowsRestructured (); + } +} + +static void +UnrealizeTree( + WindowPtr pWin, + Bool fromConfigure) +{ + register WindowPtr pChild; + UnrealizeWindowProcPtr Unrealize; + MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + + Unrealize = pWin->drawable.pScreen->UnrealizeWindow; + MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow; + pChild = pWin; + while (1) + { + if (pChild->realized) + { + pChild->realized = FALSE; + pChild->visibility = VisibilityNotViewable; +#ifdef PANORAMIX + if(!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) { + PanoramiXRes *win; + win = (PanoramiXRes*)LookupIDByType(pChild->drawable.id, + XRT_WINDOW); + if(win) + win->u.win.visibility = VisibilityNotViewable; + } +#endif + (* Unrealize)(pChild); + DeleteWindowFromAnyEvents(pChild, FALSE); + if (pChild->viewable) + { +#ifdef DO_SAVE_UNDERS + if (pChild->saveUnder) + deltaSaveUndersViewable--; +#endif + pChild->viewable = FALSE; + if (pChild->backStorage) + (*pChild->drawable.pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + if (pChild->firstChild) + { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + return; + pChild = pChild->nextSib; + } +} + +/***** + * UnmapWindow + * If the window is already unmapped, this request has no effect. + * Otherwise, the window is unmapped and an UnMapNotify event is + * generated. Cannot unmap a root window. + *****/ + +int +UnmapWindow(register WindowPtr pWin, Bool fromConfigure) +{ + register WindowPtr pParent; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if ((!pWin->mapped) || (!(pParent = pWin->parent))) + return(Success); + if (SubStrSend(pWin, pParent)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pWin->drawable.id; + event.u.unmapNotify.fromConfigure = fromConfigure; + DeliverEvents(pWin, &event, 1, NullWindow); + } + if (wasViewable && !fromConfigure) + { + pWin->valdata = UnmapValData; + (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + } + pWin->mapped = FALSE; + if (wasRealized) + UnrealizeTree(pWin, fromConfigure); + if (wasViewable) + { + if (!fromConfigure) + { + (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) + { + (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); + } + } + pWin->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (!fromConfigure && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); + } + if (wasRealized && !fromConfigure) + WindowsRestructured (); + return(Success); +} + +/***** + * UnmapSubwindows + * Performs an UnmapWindow request with the specified mode on all mapped + * children of the window, in bottom to top stacking order. + *****/ + +void +UnmapSubwindows(register WindowPtr pWin) +{ + register WindowPtr pChild, pHead; + xEvent event; + Bool wasRealized = (Bool)pWin->realized; + Bool wasViewable = (Bool)pWin->viewable; + Bool anyMarked = FALSE; + Mask parentNotify; + WindowPtr pLayerWin = NULL; + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (!pWin->firstChild) + return; + parentNotify = SubSend(pWin); + pHead = RealChildHead(pWin); + + if (wasViewable) + pLayerWin = (*pScreen->GetLayerWindow)(pWin); + + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (pChild->mapped) + { + if (parentNotify || StrSend(pChild)) + { + event.u.u.type = UnmapNotify; + event.u.unmapNotify.window = pChild->drawable.id; + event.u.unmapNotify.fromConfigure = xFalse; + DeliverEvents(pChild, &event, 1, NullWindow); + } + if (pChild->viewable) + { + pChild->valdata = UnmapValData; + anyMarked = TRUE; + } + pChild->mapped = FALSE; + if (pChild->realized) + UnrealizeTree(pChild, FALSE); + if (wasViewable) + { +#ifdef DO_SAVE_UNDERS + pChild->DIXsaveUnder = FALSE; +#endif /* DO_SAVE_UNDERS */ + if (pChild->backStorage) + (*pScreen->SaveDoomedAreas)( + pChild, &pChild->clipList, 0, 0); + } + } + } + if (wasViewable) + { + if (anyMarked) + { + if (pLayerWin->parent == pWin) + (*pScreen->MarkWindow)(pWin); + else + { + WindowPtr ptmp; + (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, + (WindowPtr *)NULL); + (*pScreen->MarkWindow)(pLayerWin->parent); + + /* Windows between pWin and pLayerWin may not have been marked */ + ptmp = pWin; + + while (ptmp != pLayerWin->parent) + { + (*pScreen->MarkWindow)(ptmp); + ptmp = ptmp->parent; + } + pHead = pWin->firstChild; + } + (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); + (*pScreen->HandleExposures)(pLayerWin->parent); + } +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); + } + if (wasRealized) + WindowsRestructured (); +} + + +void +HandleSaveSet(register ClientPtr client) +{ + register WindowPtr pParent, pWin; + register int j; + + for (j=0; jnumSaved; j++) + { + pWin = SaveSetWindow(client->saveSet[j]); +#ifdef XFIXES + if (SaveSetToRoot(client->saveSet[j])) + pParent = WindowTable[pWin->drawable.pScreen->myNum]; + else +#endif + { + pParent = pWin->parent; + while (pParent && (wClient (pParent) == client)) + pParent = pParent->parent; + } + if (pParent) + { + if (pParent != pWin->parent) + { + ReparentWindow(pWin, pParent, + pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, + pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, + client); + if(!pWin->realized && pWin->mapped) + pWin->mapped = FALSE; + } +#ifdef XFIXES + if (SaveSetRemap (client->saveSet[j])) +#endif + MapWindow(pWin, client); + } + } + xfree(client->saveSet); + client->numSaved = 0; + client->saveSet = (SaveSetElt *)NULL; +} + +/** + * + * \param x,y in root + * \param box "return" value + */ +Bool +VisibleBoundingBoxFromPoint(register WindowPtr pWin, int x, int y, BoxPtr box) +{ + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->clipList, x, y, box)) + return(TRUE); + return(FALSE); +} + +/** + * + * \param x,y in root + */ +Bool +PointInWindowIsVisible(register WindowPtr pWin, int x, int y) +{ + BoxRec box; + + if (!pWin->realized) + return (FALSE); + if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip, + x, y, &box) + && (!wInputShape(pWin) || + POINT_IN_REGION(pWin->drawable.pScreen, + wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box))) + return(TRUE); + return(FALSE); +} + + +RegionPtr +NotClippedByChildren(register WindowPtr pWin) +{ + register ScreenPtr pScreen; + RegionPtr pReg; + + pScreen = pWin->drawable.pScreen; + pReg = REGION_CREATE(pScreen, NullBox, 1); + if (pWin->parent || + screenIsSaved != SCREEN_SAVER_ON || + !HasSaverWindow (pWin->drawable.pScreen->myNum)) + { + REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize); + } + return(pReg); +} + +void +SendVisibilityNotify(WindowPtr pWin) +{ + xEvent event; +#ifndef NO_XINERAMA_PORT + unsigned int visibility = pWin->visibility; +#endif +#ifdef PANORAMIX + /* This is not quite correct yet, but it's close */ + if(!noPanoramiXExtension) { + PanoramiXRes *win; + WindowPtr pWin2; + int i, Scrnum; + + Scrnum = pWin->drawable.pScreen->myNum; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum); + + if(!win || (win->u.win.visibility == visibility)) + return; + + switch(visibility) { + case VisibilityUnobscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility == VisibilityPartiallyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + case VisibilityPartiallyObscured: + if(Scrnum) { + pWin2 = (WindowPtr)LookupIDByType(win->info[0].id, RT_WINDOW); + if (pWin2) pWin = pWin2; + } + break; + case VisibilityFullyObscured: + for(i = 0; i < PanoramiXNumScreens; i++) { + if(i == Scrnum) continue; + + pWin2 = (WindowPtr)LookupIDByType(win->info[i].id, RT_WINDOW); + + if (pWin2) { + if(pWin2->visibility != VisibilityFullyObscured) + return; + + if(!i) pWin = pWin2; + } + } + break; + } + + win->u.win.visibility = visibility; + } +#endif + + event.u.u.type = VisibilityNotify; + event.u.visibility.window = pWin->drawable.id; + event.u.visibility.state = visibility; + DeliverEvents(pWin, &event, 1, NullWindow); +} + + +#define RANDOM_WIDTH 32 + +#ifndef NOLOGOHACK +static void DrawLogo( + WindowPtr pWin +); +#endif + +void +SaveScreens(int on, int mode) +{ + int i; + int what; + int type; + + if (on == SCREEN_SAVER_FORCER) + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + if (mode == ScreenSaverReset) + what = SCREEN_SAVER_OFF; + else + what = SCREEN_SAVER_ON; + type = what; + } + else + { + what = on; + type = what; + if (what == screenIsSaved) + type = SCREEN_SAVER_CYCLE; + } + for (i = 0; i < screenInfo.numScreens; i++) + { + if (on == SCREEN_SAVER_FORCER) + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on); + if (savedScreenInfo[i].ExternalScreenSaver) + { + if ((*savedScreenInfo[i].ExternalScreenSaver) + (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER)) + continue; + } + if (type == screenIsSaved) + continue; + switch (type) { + case SCREEN_SAVER_OFF: + if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + what); + } + else if (HasSaverWindow (i)) + { + savedScreenInfo[i].pWindow = NullWindow; + FreeResource(savedScreenInfo[i].wid, RT_NONE); + } + break; + case SCREEN_SAVER_CYCLE: + if (savedScreenInfo[i].blanked == SCREEN_IS_TILED) + { + WindowPtr pWin = savedScreenInfo[i].pWindow; + /* make it look like screen saver is off, so that + * NotClippedByChildren will compute a clip list + * for the root window, so miPaintWindow works + */ + screenIsSaved = SCREEN_SAVER_OFF; +#ifndef NOLOGOHACK + if (logoScreenSaver) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE); +#endif + (*pWin->drawable.pScreen->MoveWindow)(pWin, + (short)(-(rand() % RANDOM_WIDTH)), + (short)(-(rand() % RANDOM_WIDTH)), + pWin->nextSib, VTMove); +#ifndef NOLOGOHACK + if (logoScreenSaver) + DrawLogo(pWin); +#endif + screenIsSaved = SCREEN_SAVER_ON; + } + /* + * Call the DDX saver in case it wants to do something + * at cycle time + */ + else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED) + { + (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], + type); + } + break; + case SCREEN_SAVER_ON: + if (ScreenSaverBlanking != DontPreferBlanking) + { + if ((* screenInfo.screens[i]->SaveScreen) + (screenInfo.screens[i], what)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLANKED; + continue; + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_BLACK)) + { + savedScreenInfo[i].blanked = SCREEN_IS_BLACK; + continue; + } + } + if ((ScreenSaverAllowExposures != DontAllowExposures) && + TileScreenSaver(i, SCREEN_IS_TILED)) + { + savedScreenInfo[i].blanked = SCREEN_IS_TILED; + } + else + savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED; + break; + } + } + screenIsSaved = what; + if (mode == ScreenSaverReset) + SetScreenSaverTimer(); +} + +static Bool +TileScreenSaver(int i, int kind) +{ + int j; + int result; + XID attributes[3]; + Mask mask; + WindowPtr pWin; + CursorMetricRec cm; + unsigned char *srcbits, *mskbits; + CursorPtr cursor; + XID cursorID = 0; + int attri; + + mask = 0; + attri = 0; + switch (kind) { + case SCREEN_IS_TILED: + switch (WindowTable[i]->backgroundState) { + case BackgroundPixel: + attributes[attri++] = WindowTable[i]->background.pixel; + mask |= CWBackPixel; + break; + case BackgroundPixmap: + attributes[attri++] = None; + mask |= CWBackPixmap; + break; + default: + break; + } + break; + case SCREEN_IS_BLACK: + attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel; + mask |= CWBackPixel; + break; + } + mask |= CWOverrideRedirect; + attributes[attri++] = xTrue; + + /* + * create a blank cursor + */ + + cm.width=16; + cm.height=16; + cm.xhot=8; + cm.yhot=8; + srcbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + mskbits = (unsigned char *)xalloc( BitmapBytePad(32)*16); + if (!srcbits || !mskbits) + { + xfree(srcbits); + xfree(mskbits); + cursor = 0; + } + else + { + for (j=0; jwidth + RANDOM_WIDTH, + (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH, + 0, InputOutput, mask, attributes, 0, serverClient, + wVisual (WindowTable[i]), &result); + + if (cursor) + FreeResource (cursorID, RT_NONE); + + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, + (pointer)savedScreenInfo[i].pWindow)) + return FALSE; + + if (mask & CWBackPixmap) + { + MakeRootTile (pWin); + (*pWin->drawable.pScreen->ChangeWindowAttributes)(pWin, CWBackPixmap); + } + MapWindow(pWin, serverClient); +#ifndef NOLOGOHACK + if (kind == SCREEN_IS_TILED && logoScreenSaver) + DrawLogo(pWin); +#endif + return TRUE; +} + +/* + * FindWindowWithOptional + * + * search ancestors of the given window for an entry containing + * a WindowOpt structure. Assumptions: some parent will + * contain the structure. + */ + +WindowPtr +FindWindowWithOptional (register WindowPtr w) +{ + do + w = w->parent; + while (!w->optional); + return w; +} + +/* + * CheckWindowOptionalNeed + * + * check each optional entry in the given window to see if + * the value is satisfied by the default rules. If so, + * release the optional record + */ + +void +CheckWindowOptionalNeed (register WindowPtr w) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (!w->parent) + return; + optional = w->optional; + if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate]) + return; + if (optional->otherEventMasks != 0) + return; + if (optional->otherClients != NULL) + return; + if (optional->passiveGrabs != NULL) + return; + if (optional->userProps != NULL) + return; + if (optional->backingBitPlanes != ~0L) + return; + if (optional->backingPixel != 0) + return; +#ifdef SHAPE + if (optional->boundingShape != NULL) + return; + if (optional->clipShape != NULL) + return; + if (optional->inputShape != NULL) + return; +#endif +#ifdef XINPUT + if (optional->inputMasks != NULL) + return; +#endif + parentOptional = FindWindowWithOptional(w)->optional; + if (optional->visual != parentOptional->visual) + return; + if (optional->cursor != None && + (optional->cursor != parentOptional->cursor || + w->parent->cursorIsNone)) + return; + if (optional->colormap != parentOptional->colormap) + return; + DisposeWindowOptional (w); +} + +/* + * MakeWindowOptional + * + * create an optional record and initialize it with the default + * values. + */ + +Bool +MakeWindowOptional (register WindowPtr pWin) +{ + register WindowOptPtr optional; + register WindowOptPtr parentOptional; + + if (pWin->optional) + return TRUE; + optional = (WindowOptPtr) xalloc (sizeof (WindowOptRec)); + if (!optional) + return FALSE; + optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate]; + optional->otherEventMasks = 0; + optional->otherClients = NULL; + optional->passiveGrabs = NULL; + optional->userProps = NULL; + optional->backingBitPlanes = ~0L; + optional->backingPixel = 0; +#ifdef SHAPE + optional->boundingShape = NULL; + optional->clipShape = NULL; + optional->inputShape = NULL; +#endif +#ifdef XINPUT + optional->inputMasks = NULL; +#endif + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) + { + optional->cursor = parentOptional->cursor; + optional->cursor->refcnt++; + } + else + { + optional->cursor = None; + } + optional->colormap = parentOptional->colormap; + pWin->optional = optional; + return TRUE; +} + +void +DisposeWindowOptional (register WindowPtr pWin) +{ + if (!pWin->optional) + return; + /* + * everything is peachy. Delete the optional record + * and clean up + */ + /* + * TOG changed this code to: + * + * if (pWin->cursorIsNone == FALSE) + * FreeCursor (pWin->optional->cursor, (Cursor)0); + * pWin->cursorIsNone = TRUE; + * + * This is blatently wrong; windows without optionals can have + * two different cursor values, either None or sharing their + * parents cursor. This difference is controlled by the + * cursorIsNone value; when TRUE, the window has no cursor, + * when false, it shares its cursor with its parent; TOG + * made it impossible for a window to have a cursor without + * an optional record. + */ + if (pWin->optional->cursor) + { + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->cursorIsNone = FALSE; + } + else + pWin->cursorIsNone = TRUE; + xfree (pWin->optional); + pWin->optional = NULL; +} + +#ifndef NOLOGOHACK +static void +DrawLogo(WindowPtr pWin) +{ + DrawablePtr pDraw; + ScreenPtr pScreen; + int x, y; + unsigned int width, height, size; + GC *pGC; + int thin, gap, d31; + DDXPointRec poly[4]; + ChangeGCVal fore[2], back[2]; + xrgb rgb[2]; + BITS32 fmask, bmask; + ColormapPtr cmap; + + pDraw = (DrawablePtr)pWin; + pScreen = pDraw->pScreen; + x = -pWin->origin.x; + y = -pWin->origin.y; + width = pScreen->width; + height = pScreen->height; + pGC = GetScratchGC(pScreen->rootDepth, pScreen); + if (!pGC) + return; + + if ((rand() % 100) <= 17) /* make the probability for white fairly low */ + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + if ((pWin->backgroundState == BackgroundPixel) && + (cmap = (ColormapPtr)LookupIDByType(wColormap (pWin), RT_COLORMAP))) { + Pixel querypixels[2]; + + querypixels[0] = fore[0].val; + querypixels[1] = pWin->background.pixel; + QueryColors(cmap, 2, querypixels, rgb); + if ((rgb[0].red == rgb[1].red) && + (rgb[0].green == rgb[1].green) && + (rgb[0].blue == rgb[1].blue)) { + if (fore[0].val == pScreen->blackPixel) + fore[0].val = pScreen->whitePixel; + else + fore[0].val = pScreen->blackPixel; + } + } + fore[1].val = FillSolid; + fmask = GCForeground|GCFillStyle; + if (pWin->backgroundState == BackgroundPixel) { + back[0].val = pWin->background.pixel; + back[1].val = FillSolid; + bmask = GCForeground|GCFillStyle; + } else { + back[0].val = 0; + back[1].val = 0; + dixChangeGC(NullClient, pGC, GCTileStipXOrigin|GCTileStipYOrigin, + NULL, back); + back[0].val = FillTiled; + back[1].ptr = pWin->background.pixmap; + bmask = GCFillStyle|GCTile; + } + + /* should be the same as the reference function XmuDrawLogo() */ + + size = width; + if (height < width) + size = height; + size = RANDOM_WIDTH + rand() % (size - RANDOM_WIDTH); + size &= ~1; + x += rand() % (width - size); + y += rand() % (height - size); + +/* + * Draw what will be the thin strokes. + * + * ----- + * / / + * / / + * / / + * / / + * /____/ + * d + * + * Point d is 9/44 (~1/5) of the way across. + */ + + thin = (size / 11); + if (thin < 1) thin = 1; + gap = (thin+3) / 4; + d31 = thin + thin + gap; + poly[0].x = x + size; poly[0].y = y; + poly[1].x = x + size-d31; poly[1].y = y; + poly[2].x = x + 0; poly[2].y = y + size; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for lower thin stroke. + * + * ------ + * / / + * / __ / + * / / / + * / / / + * /__/__/ + */ + + poly[0].x = x + d31/2; poly[0].y = y + size; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)+(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + d31; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase area not needed for upper thin stroke. + * + * ------ + * / / / + * /--/ / + * / / + * / / + * /_____/ + */ + + poly[0].x = x + size - d31/2; poly[0].y = y; + poly[1].x = x + size / 2; poly[1].y = y + size/2; + poly[2].x = x + (size/2)-(d31-(d31/2)); poly[2].y = y + size/2; + poly[3].x = x + size - d31; poly[3].y = y; + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Draw thick stroke. + * Point b is 1/4 of the way across. + * + * b + * ----- + * \ \ + * \ \ + * \ \ + * \ \ + * \____\ + */ + + poly[0].x = x; poly[0].y = y; + poly[1].x = x + size/4; poly[1].y = y; + poly[2].x = x + size; poly[2].y = y + size; + poly[3].x = x + size - size/4; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, fmask, NULL, fore); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + +/* + * Erase to create gap. + * + * / + * / + * / + * / + * / + */ + + poly[0].x = x + size- thin; poly[0].y = y; + poly[1].x = x + size-( thin+gap); poly[1].y = y; + poly[2].x = x + thin; poly[2].y = y + size; + poly[3].x = x + thin + gap; poly[3].y = y + size; + dixChangeGC(NullClient, pGC, bmask, NULL, back); + ValidateGC(pDraw, pGC); + (*pGC->ops->FillPolygon)(pDraw, pGC, Convex, CoordModeOrigin, 4, poly); + + FreeScratchGC(pGC); +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c new file mode 100644 index 000000000..15fdd9ff3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c @@ -0,0 +1,2286 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/Xext/xvdisp.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdisp.c,v 1.27 2003/07/16 01:38:31 dawes Exp $ */ + +/* +** File: +** +** xvdisp.c --- Xv server extension dispatch module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include +#include +#include "xvdix.h" +#ifdef MITSHM +#define _XSHM_SERVER_ +#include +#endif + +#include "Trap.h" + +#undef TEST +#undef DEBUG + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#include "xvdisp.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; + +#ifdef MITSHM +static int XineramaXvShmPutImage(ClientPtr); +#endif +static int XineramaXvPutImage(ClientPtr); +static int XineramaXvPutVideo(ClientPtr); +static int XineramaXvPutStill(ClientPtr); +static int XineramaXvSetPortAttribute(ClientPtr); +static int XineramaXvStopVideo(ClientPtr); +#endif + +/* INTERNAL */ + +static int ProcXvQueryExtension(ClientPtr); +static int ProcXvQueryAdaptors(ClientPtr); +static int ProcXvQueryEncodings(ClientPtr); +static int ProcXvPutVideo(ClientPtr); +static int ProcXvPutStill(ClientPtr); +static int ProcXvGetVideo(ClientPtr); +static int ProcXvGetStill(ClientPtr); +static int ProcXvGrabPort(ClientPtr); +static int ProcXvUngrabPort(ClientPtr); +static int ProcXvSelectVideoNotify(ClientPtr); +static int ProcXvSelectPortNotify(ClientPtr); +static int ProcXvStopVideo(ClientPtr); +static int ProcXvSetPortAttribute(ClientPtr); +static int ProcXvGetPortAttribute(ClientPtr); +static int ProcXvQueryBestSize(ClientPtr); +static int ProcXvQueryPortAttributes(ClientPtr); +static int ProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int ProcXvShmPutImage(ClientPtr); +#endif +static int ProcXvQueryImageAttributes(ClientPtr); +static int ProcXvListImageFormats(ClientPtr); + +static int SProcXvQueryExtension(ClientPtr); +static int SProcXvQueryAdaptors(ClientPtr); +static int SProcXvQueryEncodings(ClientPtr); +static int SProcXvPutVideo(ClientPtr); +static int SProcXvPutStill(ClientPtr); +static int SProcXvGetVideo(ClientPtr); +static int SProcXvGetStill(ClientPtr); +static int SProcXvGrabPort(ClientPtr); +static int SProcXvUngrabPort(ClientPtr); +static int SProcXvSelectVideoNotify(ClientPtr); +static int SProcXvSelectPortNotify(ClientPtr); +static int SProcXvStopVideo(ClientPtr); +static int SProcXvSetPortAttribute(ClientPtr); +static int SProcXvGetPortAttribute(ClientPtr); +static int SProcXvQueryBestSize(ClientPtr); +static int SProcXvQueryPortAttributes(ClientPtr); +static int SProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int SProcXvShmPutImage(ClientPtr); +#endif +static int SProcXvQueryImageAttributes(ClientPtr); +static int SProcXvListImageFormats(ClientPtr); + +static int SWriteQueryAdaptorsReply(ClientPtr, xvQueryAdaptorsReply *); +static int SWriteQueryExtensionReply(ClientPtr, xvQueryExtensionReply *); +static int SWriteQueryEncodingsReply(ClientPtr, xvQueryEncodingsReply *); +static int SWriteAdaptorInfo(ClientPtr, xvAdaptorInfo *); +static int SWriteEncodingInfo(ClientPtr, xvEncodingInfo *); +static int SWriteFormat(ClientPtr, xvFormat *); +static int SWriteAttributeInfo(ClientPtr, xvAttributeInfo *); +static int SWriteGrabPortReply(ClientPtr, xvGrabPortReply *); +static int SWriteGetPortAttributeReply(ClientPtr, xvGetPortAttributeReply *); +static int SWriteQueryBestSizeReply(ClientPtr, xvQueryBestSizeReply *); +static int SWriteQueryPortAttributesReply( + ClientPtr, xvQueryPortAttributesReply *); +static int SWriteQueryImageAttributesReply( + ClientPtr, xvQueryImageAttributesReply*); +static int SWriteListImageFormatsReply(ClientPtr, xvListImageFormatsReply*); +static int SWriteImageFormatInfo(ClientPtr, xvImageFormatInfo*); + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +/* +** ProcXvDispatch +** +** +** +*/ + +int +ProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (ProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (ProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (ProcXvQueryEncodings(client)); break; + case xv_PutVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutVideo(client)); break; + else +#endif + result = (ProcXvPutVideo(client)); break; + case xv_PutStill: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutStill(client)); break + else +#endif + result = (ProcXvPutStill(client)); break; + case xv_GetVideo: result = (ProcXvGetVideo(client)); break; + case xv_GetStill: result = (ProcXvGetStill(client)); break; + case xv_GrabPort: result = (ProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (ProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (ProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (ProcXvSelectPortNotify(client)); break; + case xv_StopVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvStopVideo(client)); break; + else +#endif + result = (ProcXvStopVideo(client)); break; + case xv_SetPortAttribute: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvSetPortAttribute(client)); break; + else +#endif + result = (ProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (ProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (ProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (ProcXvQueryPortAttributes(client)); break; + case xv_PutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutImage(client)); break; + else +#endif + result = (ProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvShmPutImage(client)); break; + else +#endif + result = (ProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (ProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (ProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +int +SProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "SProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (SProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (SProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (SProcXvQueryEncodings(client)); break; + case xv_PutVideo: result = (SProcXvPutVideo(client)); break; + case xv_PutStill: result = (SProcXvPutStill(client)); break; + case xv_GetVideo: result = (SProcXvGetVideo(client)); break; + case xv_GetStill: result = (SProcXvGetStill(client)); break; + case xv_GrabPort: result = (SProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (SProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (SProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (SProcXvSelectPortNotify(client)); break; + case xv_StopVideo: result = (SProcXvStopVideo(client)); break; + case xv_SetPortAttribute: result = (SProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (SProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (SProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (SProcXvQueryPortAttributes(client)); break; + case xv_PutImage: result = (SProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: result = (SProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (SProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (SProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; + +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize; + int na; + XvAdaptorPtr pa; + int nf; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + if(!(pWin = (WindowPtr)LookupWindow(stuff->window, client) )) + { + client->errorValue = stuff->window; + return (BadWindow); + } + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += (strlen(pa->name) + 3) & ~3; + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = totalSize >> 2; + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, ainfo.name_size, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return (client->noClientException); + +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += (strlen(pe->name) + 3) & ~3; + pe++; + } + + rep.length = totalSize >> 2; + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, einfo.name_size, pe->name); + pe++; + } + + return (client->noClientException); + +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvPutStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + register DrawablePtr pDraw; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + if(!(pDraw = (DrawablePtr)LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadWindow); + } + + return XVCALL(diSelectVideoNotify)(client, pDraw, stuff->onoff); + +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diSelectPortNotify)(client, pPort, stuff->onoff); + +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XVCALL(diGrabPort)(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; + +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diUngrabPort)(client, pPort, stuff->time); + +} + + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status; + register DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadDrawable); + } + + return XVCALL(diStopVideo)(client, pPort, pDraw); + +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diSetPortAttribute)(client, pPort, + stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diGetPortAttribute)(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L; + } + + rep.length = (rep.num_attributes * sz_xvAttributeInfo) + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = (size + 3) & ~3L; + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + + + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = (size + 3) >> 2; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, + pImage, (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + if(!(shmdesc = (ShmDescPtr)LookupIDByType(stuff->shmseg, ShmSegType))) + { + client->errorValue = stuff->shmseg; + return BadShmSegCode; + } + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#endif + +#ifdef XvMCExtension +#include "xvmcext.h" +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = xalloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, rep.length); + WriteToClient(client, rep.length << 2, (char*)offsets); + + xfree(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = rep.num_formats * sz_xvImageFormatInfo >> 2; + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < rep.num_formats; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + + + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + register char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return ProcXvQueryExtension(client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + register char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcXvQueryAdaptors(client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + register char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryEncodings(client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvGrabPort(client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvUngrabPort(client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + register char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutVideo(client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + register char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutStill(client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + register char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetVideo(client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + register char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetStill(client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvPutImage(client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->offset, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvShmPutImage(client); +} +#endif + + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return ProcXvSelectVideoNotify(client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvSelectPortNotify(client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + register char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return ProcXvStopVideo(client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvSetPortAttribute(client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvGetPortAttribute(client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + register char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvQueryBestSize(client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryPortAttributes(client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->width, n); + return ProcXvQueryImageAttributes(client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + register char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvListImageFormats(client); +} + + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)&rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + register char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + register char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + register char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + register char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + register char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + + + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)&rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)&rep); + + return Success; +} + + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)&rep); + + return Success; +} + + +#ifdef PANORAMIX + + + + +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result = Success, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result = Success, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + + +void XineramifyXv(void) +{ + ScreenPtr pScreen, screen0 = screenInfo.screens[0]; + XvScreenPtr xvsp0 = (XvScreenPtr)screen0->devPrivates[XvScreenIndex].ptr; + XvAdaptorPtr refAdapt, pAdapt; + XvAttributePtr pAttr; + XvScreenPtr xvsp; + Bool isOverlay, hasOverlay; + PanoramiXRes *port; + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k, l; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource); + + if(!xvsp0) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + refAdapt = xvsp0->pAdaptors + i; + + bzero(MatchingAdaptors, sizeof(XvAdaptorPtr) * MAXSCREENS); + + MatchingAdaptors[0] = refAdapt; + + if(!(refAdapt->type & XvInputMask)) continue; + + isOverlay = FALSE; + for(j = 0; j < refAdapt->nAttributes; j++) { + pAttr = refAdapt->pAttributes + j; + if(!strcmp(pAttr->name, "XV_COLORKEY")) { + isOverlay = TRUE; + break; + } + } + + for(j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + xvsp = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* Do not try to go on if xv is not supported on this screen */ + if (xvsp==NULL) continue ; + + /* if the adaptor has the same name it's a perfect match */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if(!strcmp(refAdapt->name, pAdapt->name)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + if(MatchingAdaptors[j]) continue; /* found it */ + + /* otherwise we only look for XvImage adaptors */ + if(!(refAdapt->type & XvImageMask)) continue; + if(refAdapt->nImages <= 0) continue; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + hasOverlay = FALSE; + for(l = 0; l < pAdapt->nAttributes; l++) { + if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + hasOverlay = TRUE; + break; + } + } + if(isOverlay && hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + else if(!isOverlay && !hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + if(MatchingAdaptors[j]) continue; /* found it */ + + /* but we'll take any XvImage pairing if we can get it */ + + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + if(!(port = xalloc(sizeof(PanoramiXRes)))) + break; + port->info[0].id = MatchingAdaptors[0]->base_id + j; + AddResource(port->info[0].id, XvXRTPort, port); + + for(k = 1; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + } + } +} + +#endif + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.NX.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.NX.original new file mode 100644 index 000000000..15fdd9ff3 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.NX.original @@ -0,0 +1,2286 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* $XdotOrg: xc/programs/Xserver/Xext/xvdisp.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdisp.c,v 1.27 2003/07/16 01:38:31 dawes Exp $ */ + +/* +** File: +** +** xvdisp.c --- Xv server extension dispatch module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include +#include +#include "xvdix.h" +#ifdef MITSHM +#define _XSHM_SERVER_ +#include +#endif + +#include "Trap.h" + +#undef TEST +#undef DEBUG + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#include "xvdisp.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; + +#ifdef MITSHM +static int XineramaXvShmPutImage(ClientPtr); +#endif +static int XineramaXvPutImage(ClientPtr); +static int XineramaXvPutVideo(ClientPtr); +static int XineramaXvPutStill(ClientPtr); +static int XineramaXvSetPortAttribute(ClientPtr); +static int XineramaXvStopVideo(ClientPtr); +#endif + +/* INTERNAL */ + +static int ProcXvQueryExtension(ClientPtr); +static int ProcXvQueryAdaptors(ClientPtr); +static int ProcXvQueryEncodings(ClientPtr); +static int ProcXvPutVideo(ClientPtr); +static int ProcXvPutStill(ClientPtr); +static int ProcXvGetVideo(ClientPtr); +static int ProcXvGetStill(ClientPtr); +static int ProcXvGrabPort(ClientPtr); +static int ProcXvUngrabPort(ClientPtr); +static int ProcXvSelectVideoNotify(ClientPtr); +static int ProcXvSelectPortNotify(ClientPtr); +static int ProcXvStopVideo(ClientPtr); +static int ProcXvSetPortAttribute(ClientPtr); +static int ProcXvGetPortAttribute(ClientPtr); +static int ProcXvQueryBestSize(ClientPtr); +static int ProcXvQueryPortAttributes(ClientPtr); +static int ProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int ProcXvShmPutImage(ClientPtr); +#endif +static int ProcXvQueryImageAttributes(ClientPtr); +static int ProcXvListImageFormats(ClientPtr); + +static int SProcXvQueryExtension(ClientPtr); +static int SProcXvQueryAdaptors(ClientPtr); +static int SProcXvQueryEncodings(ClientPtr); +static int SProcXvPutVideo(ClientPtr); +static int SProcXvPutStill(ClientPtr); +static int SProcXvGetVideo(ClientPtr); +static int SProcXvGetStill(ClientPtr); +static int SProcXvGrabPort(ClientPtr); +static int SProcXvUngrabPort(ClientPtr); +static int SProcXvSelectVideoNotify(ClientPtr); +static int SProcXvSelectPortNotify(ClientPtr); +static int SProcXvStopVideo(ClientPtr); +static int SProcXvSetPortAttribute(ClientPtr); +static int SProcXvGetPortAttribute(ClientPtr); +static int SProcXvQueryBestSize(ClientPtr); +static int SProcXvQueryPortAttributes(ClientPtr); +static int SProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int SProcXvShmPutImage(ClientPtr); +#endif +static int SProcXvQueryImageAttributes(ClientPtr); +static int SProcXvListImageFormats(ClientPtr); + +static int SWriteQueryAdaptorsReply(ClientPtr, xvQueryAdaptorsReply *); +static int SWriteQueryExtensionReply(ClientPtr, xvQueryExtensionReply *); +static int SWriteQueryEncodingsReply(ClientPtr, xvQueryEncodingsReply *); +static int SWriteAdaptorInfo(ClientPtr, xvAdaptorInfo *); +static int SWriteEncodingInfo(ClientPtr, xvEncodingInfo *); +static int SWriteFormat(ClientPtr, xvFormat *); +static int SWriteAttributeInfo(ClientPtr, xvAttributeInfo *); +static int SWriteGrabPortReply(ClientPtr, xvGrabPortReply *); +static int SWriteGetPortAttributeReply(ClientPtr, xvGetPortAttributeReply *); +static int SWriteQueryBestSizeReply(ClientPtr, xvQueryBestSizeReply *); +static int SWriteQueryPortAttributesReply( + ClientPtr, xvQueryPortAttributesReply *); +static int SWriteQueryImageAttributesReply( + ClientPtr, xvQueryImageAttributesReply*); +static int SWriteListImageFormatsReply(ClientPtr, xvListImageFormatsReply*); +static int SWriteImageFormatInfo(ClientPtr, xvImageFormatInfo*); + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +/* +** ProcXvDispatch +** +** +** +*/ + +int +ProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (ProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (ProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (ProcXvQueryEncodings(client)); break; + case xv_PutVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutVideo(client)); break; + else +#endif + result = (ProcXvPutVideo(client)); break; + case xv_PutStill: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutStill(client)); break + else +#endif + result = (ProcXvPutStill(client)); break; + case xv_GetVideo: result = (ProcXvGetVideo(client)); break; + case xv_GetStill: result = (ProcXvGetStill(client)); break; + case xv_GrabPort: result = (ProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (ProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (ProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (ProcXvSelectPortNotify(client)); break; + case xv_StopVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvStopVideo(client)); break; + else +#endif + result = (ProcXvStopVideo(client)); break; + case xv_SetPortAttribute: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvSetPortAttribute(client)); break; + else +#endif + result = (ProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (ProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (ProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (ProcXvQueryPortAttributes(client)); break; + case xv_PutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvPutImage(client)); break; + else +#endif + result = (ProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + result = (XineramaXvShmPutImage(client)); break; + else +#endif + result = (ProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (ProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (ProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +int +SProcXvDispatch(ClientPtr client) +{ + int result; + + REQUEST(xReq); + + UpdateCurrentTime(); + + /* + * Report upstream that we are + * dispatching a XVideo operation. + */ + + nxagentXvTrap = 1; + + #ifdef TEST + fprintf(stderr, "SProcXvDispatch: Going to dispatch XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + switch (stuff->data) + { + case xv_QueryExtension: result = (SProcXvQueryExtension(client)); break; + case xv_QueryAdaptors: result = (SProcXvQueryAdaptors(client)); break; + case xv_QueryEncodings: result = (SProcXvQueryEncodings(client)); break; + case xv_PutVideo: result = (SProcXvPutVideo(client)); break; + case xv_PutStill: result = (SProcXvPutStill(client)); break; + case xv_GetVideo: result = (SProcXvGetVideo(client)); break; + case xv_GetStill: result = (SProcXvGetStill(client)); break; + case xv_GrabPort: result = (SProcXvGrabPort(client)); break; + case xv_UngrabPort: result = (SProcXvUngrabPort(client)); break; + case xv_SelectVideoNotify: result = (SProcXvSelectVideoNotify(client)); break; + case xv_SelectPortNotify: result = (SProcXvSelectPortNotify(client)); break; + case xv_StopVideo: result = (SProcXvStopVideo(client)); break; + case xv_SetPortAttribute: result = (SProcXvSetPortAttribute(client)); break; + case xv_GetPortAttribute: result = (SProcXvGetPortAttribute(client)); break; + case xv_QueryBestSize: result = (SProcXvQueryBestSize(client)); break; + case xv_QueryPortAttributes: result = (SProcXvQueryPortAttributes(client)); break; + case xv_PutImage: result = (SProcXvPutImage(client)); break; +#ifdef MITSHM + case xv_ShmPutImage: result = (SProcXvShmPutImage(client)); break; +#endif + case xv_QueryImageAttributes: result = (SProcXvQueryImageAttributes(client)); break; + case xv_ListImageFormats: result = (SProcXvListImageFormats(client)); break; + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + result = (BadImplementation); break; + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + result = (BadRequest); break; + } + } + + nxagentXvTrap = 0; + + #ifdef TEST + fprintf(stderr, "ProcXvDispatch: Dispatched XVideo operation [%d] for client [%d].\n", + stuff->data, client -> index); + #endif + + return result; +} + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; + +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize; + int na; + XvAdaptorPtr pa; + int nf; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + if(!(pWin = (WindowPtr)LookupWindow(stuff->window, client) )) + { + client->errorValue = stuff->window; + return (BadWindow); + } + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += (strlen(pa->name) + 3) & ~3; + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = totalSize >> 2; + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, ainfo.name_size, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return (client->noClientException); + +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += (strlen(pe->name) + 3) & ~3; + pe++; + } + + rep.length = totalSize >> 2; + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, einfo.name_size, pe->name); + pe++; + } + + return (client->noClientException); + +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvPutStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + register DrawablePtr pDraw; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + if(!(pDraw = (DrawablePtr)LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadWindow); + } + + return XVCALL(diSelectVideoNotify)(client, pDraw, stuff->onoff); + +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diSelectPortNotify)(client, pPort, stuff->onoff); + +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XVCALL(diGrabPort)(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; + +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diUngrabPort)(client, pPort, stuff->time); + +} + + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status; + register DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadDrawable); + } + + return XVCALL(diStopVideo)(client, pPort, pDraw); + +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diSetPortAttribute)(client, pPort, + stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diGetPortAttribute)(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L; + } + + rep.length = (rep.num_attributes * sz_xvAttributeInfo) + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = (size + 3) & ~3L; + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + + + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = (size + 3) >> 2; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, + pImage, (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + if(!(shmdesc = (ShmDescPtr)LookupIDByType(stuff->shmseg, ShmSegType))) + { + client->errorValue = stuff->shmseg; + return BadShmSegCode; + } + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#endif + +#ifdef XvMCExtension +#include "xvmcext.h" +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = xalloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, rep.length); + WriteToClient(client, rep.length << 2, (char*)offsets); + + xfree(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = rep.num_formats * sz_xvImageFormatInfo >> 2; + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < rep.num_formats; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + + + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + register char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return ProcXvQueryExtension(client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + register char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcXvQueryAdaptors(client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + register char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryEncodings(client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvGrabPort(client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvUngrabPort(client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + register char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutVideo(client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + register char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutStill(client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + register char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetVideo(client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + register char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetStill(client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvPutImage(client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->offset, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvShmPutImage(client); +} +#endif + + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return ProcXvSelectVideoNotify(client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvSelectPortNotify(client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + register char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return ProcXvStopVideo(client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvSetPortAttribute(client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvGetPortAttribute(client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + register char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvQueryBestSize(client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryPortAttributes(client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->width, n); + return ProcXvQueryImageAttributes(client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + register char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvListImageFormats(client); +} + + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)&rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + register char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + register char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + register char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + register char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + register char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + + + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)&rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)&rep); + + return Success; +} + + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)&rep); + + return Success; +} + + +#ifdef PANORAMIX + + + + +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result = Success, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result = Success, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + + +void XineramifyXv(void) +{ + ScreenPtr pScreen, screen0 = screenInfo.screens[0]; + XvScreenPtr xvsp0 = (XvScreenPtr)screen0->devPrivates[XvScreenIndex].ptr; + XvAdaptorPtr refAdapt, pAdapt; + XvAttributePtr pAttr; + XvScreenPtr xvsp; + Bool isOverlay, hasOverlay; + PanoramiXRes *port; + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k, l; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource); + + if(!xvsp0) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + refAdapt = xvsp0->pAdaptors + i; + + bzero(MatchingAdaptors, sizeof(XvAdaptorPtr) * MAXSCREENS); + + MatchingAdaptors[0] = refAdapt; + + if(!(refAdapt->type & XvInputMask)) continue; + + isOverlay = FALSE; + for(j = 0; j < refAdapt->nAttributes; j++) { + pAttr = refAdapt->pAttributes + j; + if(!strcmp(pAttr->name, "XV_COLORKEY")) { + isOverlay = TRUE; + break; + } + } + + for(j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + xvsp = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* Do not try to go on if xv is not supported on this screen */ + if (xvsp==NULL) continue ; + + /* if the adaptor has the same name it's a perfect match */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if(!strcmp(refAdapt->name, pAdapt->name)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + if(MatchingAdaptors[j]) continue; /* found it */ + + /* otherwise we only look for XvImage adaptors */ + if(!(refAdapt->type & XvImageMask)) continue; + if(refAdapt->nImages <= 0) continue; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + hasOverlay = FALSE; + for(l = 0; l < pAdapt->nAttributes; l++) { + if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + hasOverlay = TRUE; + break; + } + } + if(isOverlay && hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + else if(!isOverlay && !hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + if(MatchingAdaptors[j]) continue; /* found it */ + + /* but we'll take any XvImage pairing if we can get it */ + + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + if(!(port = xalloc(sizeof(PanoramiXRes)))) + break; + port->info[0].id = MatchingAdaptors[0]->base_id + j; + AddResource(port->info[0].id, XvXRTPort, port); + + for(k = 1; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + } + } +} + +#endif + diff --git a/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.X.original b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.X.original new file mode 100644 index 000000000..21ab0b6a0 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.X.original @@ -0,0 +1,2217 @@ +/* $XdotOrg: xc/programs/Xserver/Xext/xvdisp.c,v 1.6 2005/07/03 08:53:36 daniels Exp $ */ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. + +******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/xvdisp.c,v 1.27 2003/07/16 01:38:31 dawes Exp $ */ + +/* +** File: +** +** xvdisp.c --- Xv server extension dispatch module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include +#include +#include "xvdix.h" +#ifdef MITSHM +#define _XSHM_SERVER_ +#include +#endif + +#ifdef EXTMODULE +#include "xf86_ansic.h" +#endif + +#include "xvdisp.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; + +#ifdef MITSHM +static int XineramaXvShmPutImage(ClientPtr); +#endif +static int XineramaXvPutImage(ClientPtr); +static int XineramaXvPutVideo(ClientPtr); +static int XineramaXvPutStill(ClientPtr); +static int XineramaXvSetPortAttribute(ClientPtr); +static int XineramaXvStopVideo(ClientPtr); +#endif + +/* INTERNAL */ + +static int ProcXvQueryExtension(ClientPtr); +static int ProcXvQueryAdaptors(ClientPtr); +static int ProcXvQueryEncodings(ClientPtr); +static int ProcXvPutVideo(ClientPtr); +static int ProcXvPutStill(ClientPtr); +static int ProcXvGetVideo(ClientPtr); +static int ProcXvGetStill(ClientPtr); +static int ProcXvGrabPort(ClientPtr); +static int ProcXvUngrabPort(ClientPtr); +static int ProcXvSelectVideoNotify(ClientPtr); +static int ProcXvSelectPortNotify(ClientPtr); +static int ProcXvStopVideo(ClientPtr); +static int ProcXvSetPortAttribute(ClientPtr); +static int ProcXvGetPortAttribute(ClientPtr); +static int ProcXvQueryBestSize(ClientPtr); +static int ProcXvQueryPortAttributes(ClientPtr); +static int ProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int ProcXvShmPutImage(ClientPtr); +#endif +static int ProcXvQueryImageAttributes(ClientPtr); +static int ProcXvListImageFormats(ClientPtr); + +static int SProcXvQueryExtension(ClientPtr); +static int SProcXvQueryAdaptors(ClientPtr); +static int SProcXvQueryEncodings(ClientPtr); +static int SProcXvPutVideo(ClientPtr); +static int SProcXvPutStill(ClientPtr); +static int SProcXvGetVideo(ClientPtr); +static int SProcXvGetStill(ClientPtr); +static int SProcXvGrabPort(ClientPtr); +static int SProcXvUngrabPort(ClientPtr); +static int SProcXvSelectVideoNotify(ClientPtr); +static int SProcXvSelectPortNotify(ClientPtr); +static int SProcXvStopVideo(ClientPtr); +static int SProcXvSetPortAttribute(ClientPtr); +static int SProcXvGetPortAttribute(ClientPtr); +static int SProcXvQueryBestSize(ClientPtr); +static int SProcXvQueryPortAttributes(ClientPtr); +static int SProcXvPutImage(ClientPtr); +#ifdef MITSHM +static int SProcXvShmPutImage(ClientPtr); +#endif +static int SProcXvQueryImageAttributes(ClientPtr); +static int SProcXvListImageFormats(ClientPtr); + +static int SWriteQueryAdaptorsReply(ClientPtr, xvQueryAdaptorsReply *); +static int SWriteQueryExtensionReply(ClientPtr, xvQueryExtensionReply *); +static int SWriteQueryEncodingsReply(ClientPtr, xvQueryEncodingsReply *); +static int SWriteAdaptorInfo(ClientPtr, xvAdaptorInfo *); +static int SWriteEncodingInfo(ClientPtr, xvEncodingInfo *); +static int SWriteFormat(ClientPtr, xvFormat *); +static int SWriteAttributeInfo(ClientPtr, xvAttributeInfo *); +static int SWriteGrabPortReply(ClientPtr, xvGrabPortReply *); +static int SWriteGetPortAttributeReply(ClientPtr, xvGetPortAttributeReply *); +static int SWriteQueryBestSizeReply(ClientPtr, xvQueryBestSizeReply *); +static int SWriteQueryPortAttributesReply( + ClientPtr, xvQueryPortAttributesReply *); +static int SWriteQueryImageAttributesReply( + ClientPtr, xvQueryImageAttributesReply*); +static int SWriteListImageFormatsReply(ClientPtr, xvListImageFormatsReply*); +static int SWriteImageFormatInfo(ClientPtr, xvImageFormatInfo*); + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +/* +** ProcXvDispatch +** +** +** +*/ + +int +ProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + switch (stuff->data) + { + case xv_QueryExtension: return(ProcXvQueryExtension(client)); + case xv_QueryAdaptors: return(ProcXvQueryAdaptors(client)); + case xv_QueryEncodings: return(ProcXvQueryEncodings(client)); + case xv_PutVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutVideo(client)); + else +#endif + return(ProcXvPutVideo(client)); + case xv_PutStill: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutStill(client)); + else +#endif + return(ProcXvPutStill(client)); + case xv_GetVideo: return(ProcXvGetVideo(client)); + case xv_GetStill: return(ProcXvGetStill(client)); + case xv_GrabPort: return(ProcXvGrabPort(client)); + case xv_UngrabPort: return(ProcXvUngrabPort(client)); + case xv_SelectVideoNotify: return(ProcXvSelectVideoNotify(client)); + case xv_SelectPortNotify: return(ProcXvSelectPortNotify(client)); + case xv_StopVideo: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvStopVideo(client)); + else +#endif + return(ProcXvStopVideo(client)); + case xv_SetPortAttribute: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvSetPortAttribute(client)); + else +#endif + return(ProcXvSetPortAttribute(client)); + case xv_GetPortAttribute: return(ProcXvGetPortAttribute(client)); + case xv_QueryBestSize: return(ProcXvQueryBestSize(client)); + case xv_QueryPortAttributes: return(ProcXvQueryPortAttributes(client)); + case xv_PutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvPutImage(client)); + else +#endif + return(ProcXvPutImage(client)); +#ifdef MITSHM + case xv_ShmPutImage: +#ifdef PANORAMIX + if(!noPanoramiXExtension) + return(XineramaXvShmPutImage(client)); + else +#endif + return(ProcXvShmPutImage(client)); +#endif + case xv_QueryImageAttributes: return(ProcXvQueryImageAttributes(client)); + case xv_ListImageFormats: return(ProcXvListImageFormats(client)); + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + return(BadImplementation); + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + } +} + +int +SProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + switch (stuff->data) + { + case xv_QueryExtension: return(SProcXvQueryExtension(client)); + case xv_QueryAdaptors: return(SProcXvQueryAdaptors(client)); + case xv_QueryEncodings: return(SProcXvQueryEncodings(client)); + case xv_PutVideo: return(SProcXvPutVideo(client)); + case xv_PutStill: return(SProcXvPutStill(client)); + case xv_GetVideo: return(SProcXvGetVideo(client)); + case xv_GetStill: return(SProcXvGetStill(client)); + case xv_GrabPort: return(SProcXvGrabPort(client)); + case xv_UngrabPort: return(SProcXvUngrabPort(client)); + case xv_SelectVideoNotify: return(SProcXvSelectVideoNotify(client)); + case xv_SelectPortNotify: return(SProcXvSelectPortNotify(client)); + case xv_StopVideo: return(SProcXvStopVideo(client)); + case xv_SetPortAttribute: return(SProcXvSetPortAttribute(client)); + case xv_GetPortAttribute: return(SProcXvGetPortAttribute(client)); + case xv_QueryBestSize: return(SProcXvQueryBestSize(client)); + case xv_QueryPortAttributes: return(SProcXvQueryPortAttributes(client)); + case xv_PutImage: return(SProcXvPutImage(client)); +#ifdef MITSHM + case xv_ShmPutImage: return(SProcXvShmPutImage(client)); +#endif + case xv_QueryImageAttributes: return(SProcXvQueryImageAttributes(client)); + case xv_ListImageFormats: return(SProcXvListImageFormats(client)); + default: + if (stuff->data < xvNumRequests) + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, + BadImplementation); + return(BadImplementation); + } + else + { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + } +} + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; + +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize; + int na; + XvAdaptorPtr pa; + int nf; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + if(!(pWin = (WindowPtr)LookupWindow(stuff->window, client) )) + { + client->errorValue = stuff->window; + return (BadWindow); + } + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += (strlen(pa->name) + 3) & ~3; + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = totalSize >> 2; + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, ainfo.name_size, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return (client->noClientException); + +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += (strlen(pe->name) + 3) & ~3; + pe++; + } + + rep.length = totalSize >> 2; + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, einfo.name_size, pe->name); + pe++; + } + + return (client->noClientException); + +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvPutStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diPutStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetVideo(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetVideo)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + + +static int +ProcXvGetStill(ClientPtr client) +{ + register DrawablePtr pDraw; + XvPortPtr pPort; + register GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XVCALL(diGetStill)(client, pDraw, pPort, pGC, + stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); + +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + register DrawablePtr pDraw; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + if(!(pDraw = (DrawablePtr)LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadWindow); + } + + return XVCALL(diSelectVideoNotify)(client, pDraw, stuff->onoff); + +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diSelectPortNotify)(client, pPort, stuff->onoff); + +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XVCALL(diGrabPort)(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; + +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XVCALL(diUngrabPort)(client, pPort, stuff->time); + +} + + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status; + register DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) + { + client->errorValue = stuff->drawable; + return (BadDrawable); + } + + return XVCALL(diStopVideo)(client, pPort, pDraw); + +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diSetPortAttribute)(client, pPort, + stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XVCALL(diGetPortAttribute)(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L; + } + + rep.length = (rep.num_attributes * sz_xvAttributeInfo) + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < rep.num_attributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = (size + 3) & ~3L; + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + + + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = (size + 3) >> 2; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, + pImage, (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XVCALL(diMatchPort)(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + if(!(shmdesc = (ShmDescPtr)LookupIDByType(stuff->shmseg, ShmSegType))) + { + client->errorValue = stuff->shmseg; + return BadShmSegCode; + } + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XVCALL(diPutImage)(client, pDraw, pPort, pGC, + stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, + stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#endif + +#ifdef XvMCExtension +#include "xvmcext.h" +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = xalloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, rep.length); + WriteToClient(client, rep.length << 2, (char*)offsets); + + xfree(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + if(!(pPort = LOOKUP_PORT(stuff->port, client) )) + { + client->errorValue = stuff->port; + return (_XvBadPort); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = rep.num_formats * sz_xvImageFormatInfo >> 2; + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < rep.num_formats; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + + + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + register char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return ProcXvQueryExtension(client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + register char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return ProcXvQueryAdaptors(client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + register char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryEncodings(client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvGrabPort(client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + register char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return ProcXvUngrabPort(client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + register char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutVideo(client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + register char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvPutStill(client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + register char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetVideo(client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + register char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvGetStill(client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvPutImage(client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + register char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->offset, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return ProcXvShmPutImage(client); +} +#endif + + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return ProcXvSelectVideoNotify(client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + register char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvSelectPortNotify(client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + register char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return ProcXvStopVideo(client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvSetPortAttribute(client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + register char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return ProcXvGetPortAttribute(client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + register char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return ProcXvQueryBestSize(client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvQueryPortAttributes(client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + register char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->width, n); + return ProcXvQueryImageAttributes(client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + register char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return ProcXvListImageFormats(client); +} + + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)&rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + register char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + register char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + register char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + register char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + register char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + + + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)&rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)&rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)&rep); + + return Success; +} + + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + register char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)&rep); + + return Success; +} + + +#ifdef PANORAMIX + + + + +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result = Success, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result = Success, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result = Success, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( + client, stuff->drawable, XRC_DRAWABLE, SecurityWriteAccess))) + return BadDrawable; + + if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->gc, XRT_GC, SecurityReadAccess))) + return BadGC; + + if(!(port = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->port, XvXRTPort, SecurityReadAccess))) + return _XvBadPort; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + + +void XineramifyXv(void) +{ + ScreenPtr pScreen, screen0 = screenInfo.screens[0]; + XvScreenPtr xvsp0 = (XvScreenPtr)screen0->devPrivates[XvScreenIndex].ptr; + XvAdaptorPtr refAdapt, pAdapt; + XvAttributePtr pAttr; + XvScreenPtr xvsp; + Bool isOverlay, hasOverlay; + PanoramiXRes *port; + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k, l; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource); + + if(!xvsp0) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + refAdapt = xvsp0->pAdaptors + i; + + bzero(MatchingAdaptors, sizeof(XvAdaptorPtr) * MAXSCREENS); + + MatchingAdaptors[0] = refAdapt; + + if(!(refAdapt->type & XvInputMask)) continue; + + isOverlay = FALSE; + for(j = 0; j < refAdapt->nAttributes; j++) { + pAttr = refAdapt->pAttributes + j; + if(!strcmp(pAttr->name, "XV_COLORKEY")) { + isOverlay = TRUE; + break; + } + } + + for(j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + xvsp = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr; + + /* Do not try to go on if xv is not supported on this screen */ + if (xvsp==NULL) continue ; + + /* if the adaptor has the same name it's a perfect match */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if(!strcmp(refAdapt->name, pAdapt->name)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + if(MatchingAdaptors[j]) continue; /* found it */ + + /* otherwise we only look for XvImage adaptors */ + if(!(refAdapt->type & XvImageMask)) continue; + if(refAdapt->nImages <= 0) continue; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + hasOverlay = FALSE; + for(l = 0; l < pAdapt->nAttributes; l++) { + if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + hasOverlay = TRUE; + break; + } + } + if(isOverlay && hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + else if(!isOverlay && !hasOverlay) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + if(MatchingAdaptors[j]) continue; /* found it */ + + /* but we'll take any XvImage pairing if we can get it */ + + for(k = 0; k < xvsp->nAdaptors; k++) { + pAdapt = xvsp->pAdaptors + k; + if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { + MatchingAdaptors[j] = pAdapt; + break; + } + } + } + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + if(!(port = xalloc(sizeof(PanoramiXRes)))) + break; + port->info[0].id = MatchingAdaptors[0]->base_id + j; + AddResource(port->info[0].id, XvXRTPort, port); + + for(k = 1; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + } + } +} + +#endif diff --git a/nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm b/nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm new file mode 100644 index 000000000..d35ac4ec1 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* XPM */ +static char *nxagentIconData[] = { +"16 16 5 1", +" c None", +"! c black", +"# c #FF0000", +"$ c #424242", +"% c #750202", +" ", +"############### ", +"# #$", +"# #% #######% #$", +"# #% #%%#%%#% #$", +"# #% #% #% #% #$", +"# #% #% #% #% #$", +"# #% #% #% #% #$", +"# %% #% #% #% #$", +"# #% #% #% #$", +"# #% #% #% #% #$", +"# %% %% %% %% #$", +"# #$", +"###############$", +" $$$$$$$$$$$$$$$", +" "}; diff --git a/nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm b/nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm new file mode 100644 index 000000000..497fa2511 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm @@ -0,0 +1,48 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +static char *placeholderXpm[] = { +/* columns rows colors chars-per-pixel */ +"14 16 10 1", +" c #000000", +". c #0000FF", +"X c #008400", +"o c #00FF00", +"O c #00FFFF", +"+ c #FF0000", +"@ c #FF00FF", +"# c #848484", +"$ c #BDBDBD", +"% c #FFFFFF", +/* pixels */ +" #%%%", +" %%%%%%%%%##%%", +" %$$$$$$$$#%#%", +" %$$$XX$$$#%%#", +" %$$XoX $$ ", +" %$$XXX $$$$% ", +" %$$$ $$$$$% ", +" %$$$$$$... % ", +" %$+$$$$.O. % ", +" %$@+$$$... % ", +" %$@@+$$ $% ", +" %$@@@+$$$$$% ", +" %$ +$$$$% ", +" %$$$$$$$$$$% ", +" %%%%%%%%%%%% ", +" " +}; diff --git a/nx-X11/programs/Xserver/hw/nxagent/os2Stub.c b/nx-X11/programs/Xserver/hw/nxagent/os2Stub.c new file mode 100644 index 000000000..81c479233 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/os2Stub.c @@ -0,0 +1,402 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +/* + * (c) Copyright 1996 by Sebastien Marineau + * + * + * 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 + * HOLGER VEIT 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 Sebastien Marineau shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Sebastien Marineau. + * + */ + +/* This below implements select() for calls in nxagent. It has been */ +/* somewhat optimized for improved performance, but assumes a few */ +/* things so it cannot be used as a general select. */ + +#define I_NEED_OS2_H +#include "Xpoll.h" +#include +#include +#include +#include +#define INCL_DOSSEMAPHORES +#define INCL_DOSNPIPES +#define INCL_DOSMISC +#define INCL_DOSMODULEMGR +#undef BOOL +#undef BYTE +#include + +HEV hPipeSem; +HMODULE hmod_so32dll; +static int (*os2_tcp_select)(int*,int,int,int,long); +ULONG os2_get_sys_millis(); +extern int _files[]; + +#define MAX_TCP 256 +/* These lifted from sys/emx.h. Change if that changes there! */ +#define F_SOCKET 0x10000000 +#define F_PIPE 0x20000000 + +struct select_data +{ + fd_set read_copy; + fd_set write_copy; + BOOL have_read; + BOOL have_write; + int tcp_select_mask[MAX_TCP]; + int tcp_emx_handles[MAX_TCP]; + int tcp_select_copy[MAX_TCP]; + int socket_nread; + int socket_nwrite; + int socket_ntotal; + int pipe_ntotal; + int pipe_have_write; + int max_fds; +}; + +int os2PseudoSelect(int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) +{ +static BOOL FirstTime=TRUE; +static haveTCPIP=TRUE; +ULONG timeout_ms; +ULONG postCount, start_millis,now_millis; +char faildata[16]; +struct select_data sd; +BOOL any_ready; +int np,ns, i,ready_handles,n; +APIRET rc; + +sd.have_read=FALSE; sd.have_write=FALSE; +sd.socket_nread=0; sd.socket_nwrite=0; sd.socket_ntotal=0; +sd.max_fds=31; ready_handles=0; any_ready=FALSE; +sd.pipe_ntotal=0; sd.pipe_have_write=FALSE; + +if(FirstTime){ + /* First load the so32dll.dll module and get a pointer to the SELECT function */ + + if((rc=DosLoadModule(faildata,sizeof(faildata),"SO32DLL",&hmod_so32dll))!=0){ + fprintf(stderr, "Could not load module so32dll.dll, rc = %d. Error note %s\n",rc,faildata); + haveTCPIP=FALSE; + } + if((rc = DosQueryProcAddr(hmod_so32dll, 0, "SELECT", (PPFN)&os2_tcp_select))!=0){ + fprintf(stderr, "Could not query address of SELECT, rc = %d.\n",rc); + haveTCPIP=FALSE; + } + /* Call these a first time to set the semaphore */ + /* rc = DosCreateEventSem(NULL, &hPipeSem, DC_SEM_SHARED, FALSE); + if(rc) { + fprintf(stderr, "Could not create event semaphore, rc=%d\n",rc); + return(-1); + } + rc = DosResetEventSem(hPipeSem, &postCount); */ /* Done in xtrans code for servers*/ + +fprintf(stderr, "Client select() done first-time stuff, sem handle %d.\n",hPipeSem); + + FirstTime = FALSE; +} + +/* Set up the time delay structs */ + + if(timeout!=NULL) { + timeout_ms=timeout->tv_sec*1000+timeout->tv_usec/1000; + } + else { timeout_ms=1000000; } /* This should be large enough... */ + if(timeout_ms>0) start_millis=os2_get_sys_millis(); + +/* Copy the masks */ + {FD_ZERO(&sd.read_copy);} + {FD_ZERO(&sd.write_copy);} + if(readfds!=NULL){ XFD_COPYSET(readfds,&sd.read_copy); sd.have_read=TRUE;} + if(writefds!=NULL) {XFD_COPYSET(writefds,&sd.write_copy);sd.have_write=TRUE;} + +/* And zero the original masks */ + if(sd.have_read){ FD_ZERO(readfds);} + if(sd.have_write) {FD_ZERO(writefds);} + if(exceptfds != NULL) {FD_ZERO(exceptfds);} + +/* Now we parse the fd_sets passed to select and separate pipe/sockets */ + n = os2_parse_select(&sd,nfds); + if(n == -1) { + errno = EBADF; + return (-1); + } + +/* Now we have three cases: either we have sockets, pipes, or both */ +/* We handle all three cases differently to optimize things */ + +/* Case 1: only pipes! */ + if((sd.pipe_ntotal >0) && (!sd.socket_ntotal)){ + np = os2_check_pipes(&sd,readfds,writefds); + if(np > 0){ + return (np); + } + else if (np == -1) { return(-1); } + while(!any_ready){ + rc = DosWaitEventSem(hPipeSem, timeout_ms); + /* if(rc) fprintf(stderr,"Sem-wait timeout, rc = %d\n",rc); */ + if(rc == 640) { + return(0); + } + if((rc != 0) && (rc != 95)) {errno= EBADF; return(-1);} + np = os2_check_pipes(&sd,readfds,writefds); + if (np > 0){ + return(np); + } + else if (np < 0){ return(-1); } + } + } + +/* Case 2: only sockets. Just let the os/2 tcp select do the work */ + if((sd.socket_ntotal > 0) && (!sd.pipe_ntotal)){ + ns = os2_check_sockets(&sd, readfds, writefds, timeout_ms); + return (ns); + } + +/* Case 3: combination of both */ + if((sd.socket_ntotal > 0) && (sd.pipe_ntotal)){ + np = os2_check_pipes(&sd,readfds,writefds); + if(np > 0){ + any_ready=TRUE; + ready_handles += np; + } + else if (np == -1) { return(-1); } + + ns = os2_check_sockets(&sd,readfds,writefds, 0); + if(ns>0){ + ready_handles+=ns; + any_ready = TRUE; + } + else if (ns == -1) {return(-1);} + + while (!any_ready && timeout_ms){ + + rc = DosWaitEventSem(hPipeSem, 10L); + if(rc == 0){ + np = os2_check_pipes(&sd,readfds,writefds); + if(np > 0){ + ready_handles+=np; + any_ready = TRUE; + } + else if (np == -1) { + return(-1); } + } + + ns = os2_check_sockets(&sd,readfds,writefds,exceptfds, 0); + if(ns>0){ + ready_handles+=ns; + any_ready = TRUE; + } + else if (ns == -1) {return(-1);} + + if (i%8 == 0) { + now_millis = os2_get_sys_millis(); + if((now_millis-start_millis) > timeout_ms) timeout_ms = 0; + } + i++; + } + } + +return(ready_handles); +} + + +ULONG os2_get_sys_millis() +{ + APIRET rc; + ULONG milli; + + rc = DosQuerySysInfo(14, 14, &milli, sizeof(milli)); + if(rc) { + fprintf(stderr,"Bad return code querying the millisecond counter! rc=%d\n",rc); + return(0); + } + return(milli); +} + +int os2_parse_select(sd,nfds) +struct select_data *sd; +int nfds; +{ + int i; + APIRET rc; +/* First we determine up to which descriptor we need to check. */ +/* No need to check up to 256 if we don't have to (and usually we dont...)*/ +/* Note: stuff here is hardcoded for fd_sets which are int[8] as in EMX! */ + + if(nfds > sd->max_fds){ + for(i=0;i<((FD_SETSIZE+31)/32);i++){ + if(sd->read_copy.fds_bits[i] || + sd->write_copy.fds_bits[i]) + sd->max_fds=(i*32) +32; + } + } + else { sd->max_fds = nfds; } +/* Check if result is greater than specified in select() call */ + if(sd->max_fds > nfds) sd->max_fds = nfds; + + if (sd->have_read) + { + for (i = 0; i < sd->max_fds; ++i) { + if (FD_ISSET (i, &sd->read_copy)){ + if(_files[i] & F_SOCKET) + { + sd->tcp_select_mask[sd->socket_ntotal]=_getsockhandle(i); + sd->tcp_emx_handles[sd->socket_ntotal]=i; + sd->socket_ntotal++; sd->socket_nread++; + } + else if (_files[i] & F_PIPE) + { + sd -> pipe_ntotal++; + /* rc = DosSetNPipeSem((HPIPE)i, (HSEM) hPipeSem, i); + if(rc) { fprintf(stderr,"Error SETNPIPE rc = %d\n",rc); return -1;} */ + } + } + } + } + + if (sd->have_write) + { + for (i = 0; i < sd->max_fds; ++i) { + if (FD_ISSET (i, &sd->write_copy)){ + if(_files[i] & F_SOCKET) + { + sd->tcp_select_mask[sd->socket_ntotal]=_getsockhandle(i); + sd->tcp_emx_handles[sd->socket_ntotal]=i; + sd->socket_ntotal++; sd->socket_nwrite++; + } + else if (_files[i] & F_PIPE) + { + sd -> pipe_ntotal++; + /* rc = DosSetNPipeSem((HPIPE)i, (HSEM) hPipeSem, i); + if(rc) { fprintf(stderr,"Error SETNPIPE rc = %d\n",rc); return -1;} */ + sd -> pipe_have_write=TRUE; + } + } + } + } + + +return(sd->socket_ntotal); +} + + +int os2_check_sockets(sd,readfds,writefds) +struct select_data *sd; +fd_set *readfds,*writefds; +{ + int e,i; + int j,n; + memcpy(sd->tcp_select_copy,sd->tcp_select_mask, + sd->socket_ntotal*sizeof(int)); + + e = os2_tcp_select(sd->tcp_select_copy,sd->socket_nread, + sd->socket_nwrite, 0, 0); + + if(e == 0) return(e); +/* We have something ready? */ + if(e>0){ + j = 0; n = 0; + for (i = 0; i < sd->socket_nread; ++i, ++j) + if (sd->tcp_select_copy[j] != -1) + { + FD_SET (sd->tcp_emx_handles[j], readfds); + n ++; + } + for (i = 0; i < sd->socket_nwrite; ++i, ++j) + if (sd->tcp_select_copy[j] != -1) + { + FD_SET (sd->tcp_emx_handles[j], writefds); + n ++; + } + errno = 0; + + return n; + } + if(e<0){ + /*Error -- TODO. EBADF is a good choice for now. */ + fprintf(stderr,"Error in server select! e=%d\n",e); + errno = EBADF; + return (-1); + } + } + +/* Check to see if anything is ready on pipes */ + +int os2_check_pipes(sd,readfds,writefds) +struct select_data *sd; +fd_set *readfds,*writefds; +{ +int i,e; +ULONG ulPostCount; +PIPESEMSTATE pipeSemState[128]; +APIRET rc; + e = 0; + rc = DosResetEventSem(hPipeSem,&ulPostCount); + rc = DosQueryNPipeSemState((HSEM) hPipeSem, (PPIPESEMSTATE)&pipeSemState, + sizeof(pipeSemState)); + if(rc) fprintf(stderr,"SELECT: rc from QueryNPipeSem: %d\n",rc); + i=0; + while (pipeSemState[i].fStatus != 0) { + /*fprintf(stderr,"SELECT: sem entry, stat=%d, flag=%d, key=%d,avail=%d\n", + pipeSemState[i].fStatus,pipeSemState[i].fFlag,pipeSemState[i].usKey, + pipeSemState[i].usAvail); */ + if((pipeSemState[i].fStatus == 1) && + (FD_ISSET(pipeSemState[i].usKey,&sd->read_copy))){ + FD_SET(pipeSemState[i].usKey,readfds); + e++; + } + else if((pipeSemState[i].fStatus == 2) && + (FD_ISSET(pipeSemState[i].usKey,&sd->write_copy))){ + FD_SET(pipeSemState[i].usKey,writefds); + e++; + } + else if( (pipeSemState[i].fStatus == 3) && + ( (FD_ISSET(pipeSemState[i].usKey,&sd->read_copy)) || + (FD_ISSET(pipeSemState[i].usKey,&sd->write_copy)) )){ + errno = EBADF; + /* fprintf(stderr,"Pipe has closed down, fd=%d\n",pipeSemState[i].usKey); */ + return (-1); + } + i++; + } /* endwhile */ + /*fprintf(stderr,"Done listing pipe sem entries, total %d entries, total ready entries %d\n" i,e);*/ +errno = 0; +return(e); +} + diff --git a/nx-X11/programs/Xserver/hw/nxagent/screensaver b/nx-X11/programs/Xserver/hw/nxagent/screensaver new file mode 100644 index 000000000..b9408a2b7 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/screensaver @@ -0,0 +1,703 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2003 NoMachine, http://www.nomachine.com. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#define screensaver_width 256 +#define screensaver_height 256 +static unsigned char screensaver_bits[] = { + 0xa8, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x40, 0x55, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x55, 0x05, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0xa0, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xaa, + 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0xaa, 0x0a, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0x2a, 0x80, 0x02, 0x80, 0xaa, 0xaa, 0x82, 0x0a, 0xa8, 0x28, 0x80, + 0x8a, 0x80, 0x2a, 0x80, 0x80, 0x8a, 0xa2, 0x82, 0x0a, 0xaa, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x80, 0x82, 0x41, 0x40, 0x00, 0x50, + 0x55, 0x41, 0x00, 0x00, 0x04, 0x00, 0x54, 0x40, 0x10, 0x00, 0x40, 0x00, + 0x51, 0x55, 0x00, 0x15, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x10, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x8a, 0x02, 0x00, 0x02, + 0x00, 0x20, 0xa2, 0x00, 0x80, 0x00, 0x08, 0x00, 0xaa, 0x2a, 0x00, 0x2a, + 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, + 0x01, 0x00, 0x01, 0x50, 0x45, 0x05, 0x00, 0x01, 0x10, 0x10, 0x40, 0x11, + 0x40, 0x00, 0x44, 0x00, 0x50, 0x15, 0x01, 0x15, 0x04, 0x00, 0x40, 0x00, + 0x05, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x50, 0x20, 0x00, 0x00, 0xa2, + 0xaa, 0x2a, 0x00, 0x00, 0x02, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x00, 0x00, + 0xa2, 0xaa, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x01, 0x40, 0x44, 0x15, 0x10, 0x01, + 0x10, 0x10, 0x40, 0x01, 0x40, 0x00, 0x00, 0x00, 0x54, 0x55, 0x41, 0x45, + 0x04, 0x00, 0x40, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x54, + 0x20, 0x80, 0x00, 0x82, 0xaa, 0x0a, 0x00, 0x00, 0x22, 0x00, 0x80, 0x0a, + 0x00, 0x00, 0x82, 0x00, 0xa0, 0x8a, 0x22, 0x02, 0x00, 0x08, 0x20, 0x00, + 0xa8, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x2a, 0x10, 0x40, 0x00, 0x01, + 0x54, 0x45, 0x10, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, + 0x50, 0x45, 0x05, 0x41, 0x00, 0x04, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x28, 0x00, 0xaa, 0xaa, 0x0a, 0x0a, 0x00, + 0x20, 0x08, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0xa8, 0xa2, 0x22, 0x2a, + 0x00, 0x00, 0x0a, 0x00, 0xa8, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0a, + 0x50, 0x05, 0x00, 0x01, 0x55, 0x45, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x40, 0x55, 0x11, 0x00, 0x00, 0x54, 0x01, 0x00, + 0x44, 0x01, 0x00, 0x00, 0x05, 0x40, 0x00, 0x05, 0x00, 0x08, 0x00, 0x80, + 0xaa, 0xaa, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x80, 0x00, + 0x80, 0xaa, 0x28, 0x20, 0x00, 0x00, 0x02, 0x00, 0x80, 0x02, 0x00, 0x00, + 0x28, 0x00, 0x80, 0x02, 0x10, 0x10, 0x00, 0x01, 0x54, 0x45, 0x01, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x55, 0x14, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x40, 0x40, 0x01, + 0x08, 0x00, 0x80, 0x00, 0xa8, 0xa2, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xa0, 0xaa, 0x00, 0x80, 0x28, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x80, 0x02, 0x00, 0x00, 0x80, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x14, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x40, 0x00, 0x00, 0x08, 0x20, 0x80, 0x00, 0x08, 0x08, 0x80, 0x80, + 0x80, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x8a, 0x00, + 0x02, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, + 0x10, 0x10, 0x00, 0x01, 0x10, 0x45, 0x55, 0x01, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, + 0x20, 0xa2, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x80, 0x00, 0x02, 0x04, 0x00, 0x40, 0x00, 0x04, 0x04, 0x40, 0x40, + 0x00, 0x01, 0x00, 0x04, 0x04, 0x00, 0x00, 0x01, 0x00, 0x51, 0x45, 0x05, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x45, 0x01, + 0x2a, 0x80, 0xaa, 0xaa, 0x82, 0xaa, 0x2a, 0xa0, 0x02, 0x02, 0x80, 0xa8, + 0x00, 0x2a, 0xa0, 0x02, 0x80, 0xa2, 0x00, 0xa0, 0xa0, 0x0a, 0xa0, 0x00, + 0x00, 0x00, 0x80, 0x88, 0x02, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x41, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa0, 0xaa, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x55, 0x55, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xa8, 0xaa, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x2a, 0x20, 0x00, 0x00, 0x41, 0x05, 0x55, 0x54, 0x11, 0x04, 0x00, 0x14, + 0x40, 0x10, 0x44, 0x15, 0x15, 0x00, 0x00, 0x50, 0x01, 0x00, 0x50, 0x55, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x10, 0x50, 0x40, + 0x82, 0x08, 0x02, 0x08, 0x20, 0x08, 0x00, 0x22, 0xa0, 0x20, 0x88, 0x00, + 0x22, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x80, 0x02, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x08, 0x88, 0x20, 0x44, 0x10, 0x01, 0x04, + 0x50, 0x04, 0x00, 0x41, 0x10, 0x11, 0x44, 0x00, 0x41, 0x00, 0x00, 0x54, + 0x41, 0x00, 0x40, 0x55, 0x15, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x11, 0x04, 0x11, 0x80, 0x20, 0x02, 0x08, 0xa0, 0x08, 0x00, 0x02, + 0x88, 0x20, 0x88, 0x00, 0x82, 0x00, 0x00, 0x2a, 0x22, 0x00, 0x80, 0xaa, + 0x2a, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x08, 0x20, + 0x40, 0x10, 0x01, 0x04, 0x50, 0x04, 0x00, 0x01, 0x04, 0x41, 0x44, 0x00, + 0x41, 0x00, 0x00, 0x15, 0x05, 0x14, 0x15, 0x50, 0x10, 0x05, 0x40, 0x41, + 0x41, 0x10, 0x45, 0x05, 0x50, 0x04, 0x04, 0x10, 0x80, 0x20, 0x02, 0x08, + 0xa0, 0x08, 0x00, 0x02, 0x08, 0x22, 0x82, 0x00, 0x82, 0x00, 0x00, 0x0a, + 0x2a, 0x22, 0x8a, 0x22, 0x22, 0x08, 0x80, 0x22, 0x22, 0x88, 0x88, 0x02, + 0x28, 0x02, 0x08, 0x20, 0x40, 0x10, 0x15, 0x54, 0x10, 0x05, 0x00, 0x14, + 0x04, 0x41, 0x44, 0x05, 0x41, 0x00, 0x00, 0x05, 0x50, 0x01, 0x41, 0x04, + 0x05, 0x11, 0x00, 0x05, 0x44, 0x44, 0x50, 0x00, 0x10, 0x05, 0x50, 0x10, + 0x80, 0x0a, 0x02, 0x08, 0x20, 0x0a, 0x00, 0x20, 0xa8, 0x82, 0x82, 0x00, + 0x2a, 0x00, 0x80, 0x02, 0x22, 0x02, 0x82, 0x20, 0x20, 0x08, 0x20, 0x88, + 0x82, 0x88, 0x8a, 0x00, 0x88, 0x0a, 0x80, 0x20, 0x40, 0x04, 0x01, 0x04, + 0x10, 0x05, 0x00, 0x40, 0x04, 0x41, 0x41, 0x00, 0x11, 0x00, 0x40, 0x01, + 0x41, 0x41, 0x41, 0x14, 0x15, 0x11, 0x40, 0x44, 0x04, 0x44, 0x40, 0x00, + 0x44, 0x15, 0x00, 0x11, 0x80, 0x08, 0x02, 0x08, 0x20, 0x0a, 0x00, 0x80, + 0x08, 0x82, 0x82, 0x00, 0x22, 0x00, 0xa0, 0x00, 0x22, 0x22, 0x82, 0x20, + 0x22, 0x0a, 0x20, 0x28, 0x82, 0x82, 0x88, 0x00, 0x88, 0x2a, 0x00, 0x22, + 0x44, 0x10, 0x01, 0x04, 0x10, 0x04, 0x00, 0x41, 0x04, 0x01, 0x41, 0x00, + 0x41, 0x00, 0x50, 0x01, 0x14, 0x14, 0x01, 0x55, 0x10, 0x15, 0x40, 0x45, + 0x05, 0x01, 0x45, 0x00, 0x04, 0x55, 0x04, 0x11, 0x82, 0x20, 0x02, 0x08, + 0x20, 0x08, 0x00, 0x22, 0x08, 0x82, 0x80, 0x00, 0x82, 0x00, 0xa8, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xaa, 0x88, 0x20, 0x41, 0x10, 0x55, 0x54, 0x11, 0x04, 0x00, 0x14, + 0x04, 0x01, 0x41, 0x15, 0x41, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x54, 0x51, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x15, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xa8, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x15, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x14, 0x40, 0x01, 0x41, 0x40, 0x01, 0x14, 0x10, 0x01, 0x00, 0x40, + 0x01, 0x04, 0x14, 0x14, 0x14, 0x10, 0x04, 0x00, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xaa, 0x00, 0x00, 0x00, 0x80, 0x82, 0xa0, 0x20, 0x82, + 0xa2, 0x20, 0x02, 0x22, 0x28, 0x02, 0x00, 0x08, 0x8a, 0x22, 0x08, 0x08, + 0x22, 0x28, 0x0a, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x54, + 0x01, 0x00, 0x00, 0x40, 0x41, 0x40, 0x10, 0x04, 0x11, 0x11, 0x04, 0x41, + 0x10, 0x04, 0x00, 0x04, 0x04, 0x40, 0x10, 0x00, 0x41, 0x10, 0x11, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xaa, 0x02, 0x00, 0x00, 0xa0, + 0x82, 0x80, 0x08, 0x08, 0x02, 0x08, 0x88, 0x80, 0x08, 0x08, 0x00, 0x08, + 0x08, 0x20, 0x20, 0x80, 0x80, 0x20, 0x00, 0x00, 0x10, 0x50, 0x14, 0x14, + 0x45, 0x05, 0x40, 0x05, 0x41, 0x14, 0x15, 0x50, 0x41, 0x01, 0x04, 0x00, + 0x01, 0x04, 0x50, 0x00, 0x11, 0x04, 0x00, 0x14, 0x00, 0x40, 0x10, 0x44, + 0x00, 0x11, 0x00, 0x00, 0xa0, 0x88, 0x22, 0xa2, 0x88, 0x08, 0x00, 0x2a, + 0x82, 0x22, 0x22, 0xa8, 0x80, 0x0a, 0x08, 0x00, 0x02, 0xa8, 0x8a, 0xaa, + 0x08, 0x08, 0x00, 0xa8, 0x00, 0x2a, 0x20, 0x80, 0xaa, 0x20, 0x00, 0x00, + 0x00, 0x05, 0x04, 0x15, 0x55, 0x04, 0x40, 0x04, 0x50, 0x54, 0x01, 0x54, + 0x00, 0x54, 0x04, 0x00, 0x01, 0x04, 0x40, 0x00, 0x10, 0x04, 0x00, 0x40, + 0x05, 0x41, 0x40, 0x40, 0x00, 0x10, 0x00, 0x00, 0x80, 0x08, 0x02, 0x82, + 0x80, 0x08, 0x80, 0x20, 0x02, 0x02, 0x02, 0x2a, 0x00, 0xa0, 0x08, 0x00, + 0x02, 0x08, 0x80, 0x00, 0x08, 0x08, 0x00, 0x00, 0x8a, 0x20, 0x20, 0x82, + 0x00, 0x20, 0x00, 0x00, 0x10, 0x45, 0x04, 0x11, 0x51, 0x04, 0x50, 0x44, + 0x44, 0x44, 0x01, 0x15, 0x00, 0x40, 0x05, 0x00, 0x01, 0x04, 0x40, 0x00, + 0x10, 0x04, 0x00, 0x00, 0x54, 0x40, 0x40, 0x41, 0x00, 0x10, 0x00, 0x00, + 0xa0, 0x28, 0x02, 0x0a, 0x8a, 0x08, 0x20, 0x0a, 0x0a, 0x28, 0x02, 0x0a, + 0x00, 0x80, 0x08, 0x00, 0x02, 0x08, 0x80, 0x00, 0x08, 0x08, 0x00, 0x00, + 0x88, 0x20, 0x80, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x05, 0x40, 0x00, 0x11, 0x00, + 0x01, 0x10, 0x10, 0x01, 0x11, 0x04, 0x00, 0x04, 0x50, 0x40, 0x41, 0x01, + 0x01, 0x11, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, + 0xaa, 0x00, 0x80, 0x02, 0x80, 0x80, 0x20, 0x02, 0x02, 0x20, 0x08, 0x82, + 0x08, 0x08, 0x00, 0x08, 0x88, 0x20, 0x80, 0x00, 0x82, 0x20, 0x00, 0x00, + 0x00, 0x40, 0x01, 0x10, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x40, 0x01, + 0x40, 0x14, 0x40, 0x41, 0x05, 0x40, 0x01, 0x14, 0x14, 0x14, 0x00, 0x44, + 0x01, 0x45, 0x00, 0x00, 0x14, 0x54, 0x00, 0x00, 0x00, 0x80, 0x02, 0x08, + 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x50, + 0x55, 0x05, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x02, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0xa8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, + 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0xaa, 0x0a, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x15, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x15, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x8a, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0xa2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x05, 0x50, 0x00, 0x50, 0x40, 0x45, 0x11, 0x00, 0x50, + 0x40, 0x41, 0x01, 0x00, 0x14, 0x00, 0x51, 0x40, 0x40, 0x00, 0x05, 0x14, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0a, + 0x88, 0x02, 0xaa, 0xa8, 0x80, 0x00, 0x00, 0xaa, 0xa8, 0xa2, 0x02, 0x00, + 0xa2, 0xa0, 0x22, 0xa8, 0xa0, 0xa0, 0x8a, 0x2a, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x14, 0x04, 0x01, 0x45, 0x51, + 0x04, 0x40, 0x00, 0x45, 0x41, 0x51, 0x01, 0x00, 0x41, 0x50, 0x54, 0x50, + 0x50, 0x50, 0x14, 0x14, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0xa2, 0xa0, 0x02, 0xa0, 0x88, 0x82, + 0xa0, 0x88, 0x02, 0x80, 0x82, 0x28, 0x28, 0xa0, 0x20, 0x28, 0x08, 0x8a, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x45, 0x54, 0x00, + 0x14, 0x40, 0x41, 0x50, 0x05, 0x51, 0x10, 0x41, 0x41, 0x41, 0x01, 0x00, + 0x05, 0x14, 0x10, 0x50, 0x40, 0x10, 0x14, 0x54, 0x04, 0x00, 0x41, 0x55, + 0x04, 0x45, 0x01, 0x04, 0x20, 0x02, 0x08, 0x00, 0x2a, 0xa0, 0x00, 0xa0, + 0x8a, 0x20, 0xa8, 0xa2, 0xa0, 0xa0, 0x00, 0x80, 0x0a, 0x28, 0x28, 0xa0, + 0x20, 0x28, 0x0a, 0x2a, 0x00, 0x00, 0x22, 0x0a, 0x80, 0x88, 0x02, 0x88, + 0x04, 0x50, 0x01, 0x00, 0x54, 0x40, 0x01, 0x50, 0x15, 0x10, 0x14, 0x51, + 0x40, 0x41, 0x01, 0x00, 0x15, 0x14, 0x14, 0x40, 0x11, 0x14, 0x05, 0x14, + 0x00, 0x40, 0x10, 0x00, 0x15, 0x45, 0x04, 0x01, 0x00, 0x00, 0x08, 0x00, + 0xa8, 0xa0, 0x00, 0x28, 0x8a, 0x08, 0x0a, 0x28, 0xa0, 0xa0, 0x00, 0x00, + 0x2a, 0x0a, 0x28, 0xa0, 0x08, 0x8a, 0x02, 0x0a, 0x00, 0x80, 0x00, 0x08, + 0x80, 0x00, 0x00, 0x82, 0x44, 0x11, 0x00, 0x00, 0x50, 0x50, 0x00, 0x10, + 0x05, 0x40, 0x15, 0x05, 0x50, 0x50, 0x00, 0x00, 0x14, 0x14, 0x14, 0x40, + 0x11, 0x54, 0x00, 0x05, 0x00, 0x00, 0x11, 0x00, 0x01, 0x40, 0x04, 0x44, + 0x80, 0x20, 0x0a, 0x00, 0xa0, 0xa0, 0x00, 0x88, 0x82, 0xa8, 0x0a, 0x00, + 0xa0, 0xa0, 0x00, 0x00, 0x28, 0x0a, 0x0a, 0xa0, 0x08, 0x0a, 0x00, 0x0a, + 0x00, 0x00, 0x22, 0x0a, 0xa2, 0x00, 0x00, 0x88, 0x01, 0x40, 0x15, 0x00, + 0x50, 0x51, 0x40, 0x00, 0x01, 0x51, 0x15, 0x00, 0x50, 0x50, 0x00, 0x00, + 0x54, 0x14, 0x54, 0x40, 0x05, 0x14, 0x00, 0x05, 0x00, 0x40, 0x41, 0x15, + 0x14, 0x45, 0x04, 0x05, 0x00, 0x00, 0x00, 0x80, 0xa0, 0xa0, 0x20, 0x88, + 0x80, 0xaa, 0x08, 0x82, 0x28, 0x28, 0x02, 0x20, 0x28, 0x0a, 0x2a, 0xa0, + 0x02, 0x0a, 0x88, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x40, 0x11, 0x44, 0x00, 0x55, 0x14, 0x44, + 0x50, 0x50, 0x01, 0x40, 0x10, 0x54, 0x15, 0x40, 0x01, 0x14, 0x04, 0x45, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x22, 0xa0, 0x0a, 0x00, 0x00, 0x0a, 0x2a, 0x20, 0x28, 0xa8, 0x00, 0xa0, + 0x08, 0xa8, 0x08, 0xa0, 0x00, 0xa8, 0x82, 0x82, 0x02, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x05, 0x00, + 0x00, 0x54, 0x55, 0x10, 0x50, 0x50, 0x00, 0x00, 0x05, 0x50, 0x04, 0x40, + 0x00, 0x50, 0x40, 0x05, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x80, 0xaa, 0x2a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, + 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0x55, 0x55, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, + 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa8, 0xaa, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x50, 0x55, + 0x05, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x28, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x80, 0xaa, + 0x2a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x50, 0x15, + 0x55, 0x11, 0x55, 0x00, 0x15, 0x00, 0x54, 0x01, 0x00, 0x54, 0x01, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x00, 0x20, 0x82, 0x20, 0x08, 0x82, 0x00, 0x22, 0x80, + 0x08, 0x08, 0x28, 0xa2, 0x28, 0x20, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa2, + 0x00, 0x04, 0x41, 0x10, 0x04, 0x11, 0x00, 0x40, 0x10, 0x14, 0x10, 0x54, + 0x54, 0x11, 0x10, 0x00, 0x01, 0x00, 0x50, 0x14, 0x15, 0x05, 0x45, 0x01, + 0x50, 0x50, 0x44, 0x14, 0x05, 0x00, 0x04, 0x40, 0x20, 0x02, 0x22, 0x02, + 0x22, 0x08, 0x20, 0x20, 0x00, 0x08, 0x20, 0xa8, 0x28, 0x22, 0x08, 0x80, + 0x02, 0x00, 0x88, 0x22, 0xa2, 0x88, 0x28, 0x02, 0x88, 0x80, 0x22, 0xa2, + 0x08, 0x00, 0x08, 0x22, 0x00, 0x04, 0x41, 0x00, 0x04, 0x00, 0x01, 0x40, + 0x00, 0x10, 0x40, 0x04, 0x11, 0x10, 0x04, 0x10, 0x05, 0x00, 0x10, 0x04, + 0x01, 0x55, 0x45, 0x04, 0x10, 0x50, 0x44, 0x15, 0x01, 0x00, 0x14, 0x10, + 0x00, 0x2a, 0xa0, 0x02, 0x2a, 0x20, 0x22, 0x80, 0x02, 0x22, 0x20, 0x02, + 0x0a, 0xa0, 0x02, 0x08, 0x0a, 0x00, 0x20, 0x02, 0x82, 0x80, 0x20, 0x02, + 0x80, 0x88, 0x28, 0x82, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x44, 0x40, 0x01, + 0x14, 0x00, 0x04, 0x00, 0x05, 0x10, 0x40, 0x00, 0x11, 0x10, 0x05, 0x04, + 0x14, 0x00, 0x44, 0x44, 0x01, 0x51, 0x44, 0x04, 0x10, 0x45, 0x14, 0x11, + 0x01, 0x00, 0x50, 0x11, 0x00, 0x82, 0x20, 0x02, 0x22, 0x20, 0x28, 0x20, + 0x08, 0x2a, 0x80, 0x02, 0x02, 0x20, 0x08, 0x00, 0x00, 0x00, 0x28, 0x28, + 0x02, 0x8a, 0x22, 0x02, 0xa0, 0xa8, 0x08, 0x8a, 0x00, 0x00, 0x80, 0x22, + 0x00, 0x04, 0x41, 0x10, 0x04, 0x01, 0x10, 0x00, 0x10, 0x41, 0x40, 0x01, + 0x11, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x51, 0x20, 0x82, 0x20, 0x00, + 0x02, 0x20, 0x28, 0x20, 0x88, 0x20, 0x80, 0x00, 0x82, 0x20, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x22, 0x10, 0x04, 0x45, 0x10, 0x04, 0x01, 0x10, 0x40, + 0x04, 0x40, 0x00, 0x00, 0x41, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x41, + 0x8a, 0x0a, 0xaa, 0x8a, 0xaa, 0xa8, 0x20, 0xa0, 0x82, 0xa2, 0x80, 0x80, + 0xaa, 0xa8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0xa2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x10, 0x50, + 0x41, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x15, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xa0, 0x80, 0x02, 0xa8, 0x28, + 0x0a, 0xa0, 0x02, 0xa8, 0x00, 0x8a, 0x02, 0x28, 0x00, 0x00, 0x00, 0x0a, + 0x28, 0x80, 0x2a, 0x80, 0x22, 0x80, 0x0a, 0x00, 0xa8, 0x00, 0x28, 0x2a, + 0x00, 0x05, 0x00, 0x50, 0x00, 0x00, 0x55, 0x51, 0x14, 0x14, 0x54, 0x54, + 0x01, 0x54, 0x01, 0x50, 0x50, 0x05, 0x00, 0x05, 0x00, 0x50, 0x55, 0x40, + 0x51, 0x50, 0x15, 0x00, 0x54, 0x05, 0x14, 0x55, 0x00, 0x0a, 0x00, 0xa0, + 0x00, 0x80, 0xaa, 0x2a, 0x2a, 0x08, 0x2a, 0xa8, 0x02, 0xaa, 0x02, 0xa0, + 0xa0, 0x02, 0x00, 0x0a, 0x00, 0xa8, 0xaa, 0x80, 0x2a, 0xa8, 0x2a, 0x80, + 0xaa, 0x0a, 0xa8, 0xaa, 0x01, 0x05, 0x00, 0x50, 0x05, 0x40, 0x55, 0x55, + 0x14, 0x00, 0x14, 0x50, 0x05, 0x54, 0x01, 0x40, 0x51, 0x01, 0x00, 0x55, + 0x00, 0x54, 0x55, 0x41, 0x15, 0x54, 0x55, 0x40, 0x55, 0x15, 0x54, 0x55, + 0x02, 0x0a, 0x00, 0xa0, 0x0a, 0xa0, 0x02, 0x2a, 0x2a, 0x00, 0x0a, 0x88, + 0x0a, 0x2a, 0x00, 0x80, 0xaa, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0xa0, 0xa2, + 0x0a, 0x2a, 0xa8, 0xa0, 0x0a, 0x0a, 0xaa, 0xa0, 0x01, 0x14, 0x01, 0x40, + 0x55, 0x50, 0x01, 0x14, 0x14, 0x00, 0x05, 0x04, 0x15, 0x15, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x54, 0x05, 0x14, 0x40, 0x45, 0x05, 0x15, 0x50, 0x41, + 0x01, 0x14, 0x54, 0x40, 0x02, 0xa8, 0x00, 0x80, 0xaa, 0xa8, 0x00, 0x2a, + 0x28, 0x88, 0x02, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x0a, 0x0a, 0xa0, 0xa2, 0x82, 0x0a, 0xa0, 0xa0, 0x00, 0x28, 0x2a, 0xa0, + 0x01, 0x50, 0x00, 0x00, 0x55, 0x50, 0x00, 0x14, 0x54, 0x54, 0x05, 0x15, + 0x14, 0x15, 0x00, 0x00, 0x11, 0x00, 0x00, 0x50, 0x05, 0x15, 0x00, 0x40, + 0x01, 0x05, 0x40, 0x51, 0x00, 0x14, 0x14, 0x40, 0x00, 0xa8, 0x00, 0x00, + 0xa8, 0x28, 0x00, 0x28, 0x28, 0xa8, 0x02, 0x80, 0x0a, 0x0a, 0x00, 0x80, + 0x08, 0x00, 0x00, 0x80, 0x8a, 0x0a, 0x00, 0xa0, 0x80, 0xaa, 0xaa, 0xa8, + 0xaa, 0x2a, 0x0a, 0xa0, 0x01, 0x44, 0x01, 0x00, 0x50, 0x55, 0x00, 0x14, + 0x50, 0x14, 0x01, 0x00, 0x15, 0x05, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, + 0x15, 0x05, 0x00, 0x50, 0x41, 0x55, 0x55, 0x51, 0x55, 0x15, 0x15, 0x40, + 0x00, 0x80, 0x02, 0x00, 0xa0, 0x28, 0x00, 0x0a, 0x28, 0x0a, 0x02, 0x00, + 0x8a, 0x0a, 0x00, 0xa0, 0x2a, 0x00, 0x00, 0x00, 0x8a, 0x0a, 0x00, 0xa0, + 0x80, 0xaa, 0xaa, 0xa8, 0xaa, 0x2a, 0x0a, 0xa0, 0x01, 0x40, 0x01, 0x00, + 0x50, 0x55, 0x00, 0x14, 0x50, 0x05, 0x00, 0x00, 0x14, 0x05, 0x00, 0x50, + 0x50, 0x00, 0x00, 0x00, 0x15, 0x05, 0x00, 0x50, 0x40, 0x55, 0x55, 0x51, + 0x55, 0x15, 0x05, 0x50, 0x00, 0x80, 0x02, 0x2a, 0xa8, 0x28, 0x00, 0x0a, + 0xa8, 0x0a, 0x80, 0xaa, 0x82, 0x02, 0x00, 0x20, 0xa0, 0x00, 0xa0, 0x82, + 0x8a, 0x0a, 0x00, 0xa0, 0x80, 0x02, 0x00, 0x28, 0x00, 0x00, 0x0a, 0xa0, + 0x00, 0x00, 0x05, 0x14, 0x50, 0x54, 0x00, 0x15, 0x50, 0x05, 0x40, 0x55, + 0x01, 0x05, 0x00, 0x10, 0x40, 0x01, 0x40, 0x01, 0x05, 0x15, 0x50, 0x51, + 0x40, 0x01, 0x00, 0x50, 0x00, 0x00, 0x05, 0x50, 0x00, 0x00, 0x0a, 0x2a, + 0xa8, 0xa8, 0x80, 0x0a, 0xa0, 0x02, 0x80, 0x0a, 0x80, 0x02, 0x00, 0x08, + 0x80, 0x02, 0xa0, 0x82, 0x0a, 0x2a, 0xa8, 0xa0, 0x80, 0x02, 0x2a, 0xa8, + 0x80, 0x8a, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x54, 0x55, 0x50, 0x55, 0x05, + 0x50, 0x01, 0x00, 0x00, 0x44, 0x05, 0x00, 0x04, 0x00, 0x05, 0x40, 0x55, + 0x05, 0x54, 0x55, 0x50, 0x00, 0x55, 0x15, 0x50, 0x55, 0x05, 0x05, 0x50, + 0x00, 0x00, 0x00, 0xa8, 0x2a, 0xa0, 0xaa, 0x0a, 0xa0, 0x00, 0x08, 0x00, + 0x8a, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x80, 0xaa, 0x02, 0xaa, 0x2a, 0x28, + 0x80, 0xaa, 0x0a, 0xa0, 0xaa, 0x82, 0x02, 0x28, 0x00, 0x00, 0x00, 0x50, + 0x15, 0x40, 0x55, 0x05, 0x40, 0x01, 0x10, 0x00, 0x55, 0x01, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x55, 0x01, 0x54, 0x15, 0x50, 0x00, 0x55, 0x05, 0x40, + 0x55, 0x01, 0x05, 0x50, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x80, 0x0a, 0x0a, + 0xa0, 0x00, 0x00, 0xa0, 0xaa, 0x02, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0xa0, 0x0a, 0x28, 0x00, 0xa8, 0x00, 0x80, 0x2a, 0x80, 0x02, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + 0x55, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0xa0, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, + 0xaa, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x55, 0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xaa, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x45, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x22, 0xa0, 0x22, 0xa8, 0x0a, 0xa8, 0x00, + 0xa8, 0xa0, 0x28, 0x80, 0xaa, 0x22, 0x28, 0xa0, 0x02, 0x2a, 0x2a, 0xa0, + 0x02, 0x8a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x15, 0x50, 0x15, 0x54, 0x15, 0x54, 0x01, 0x55, 0x41, 0x55, 0x00, + 0x55, 0x11, 0x54, 0x50, 0x05, 0x54, 0x54, 0x54, 0x05, 0x54, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x08, 0x08, + 0x20, 0x08, 0x02, 0x82, 0x82, 0x82, 0x82, 0x00, 0xaa, 0x08, 0x20, 0x20, + 0x08, 0x08, 0x08, 0x0a, 0x0a, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, 0x04, 0x10, 0x10, 0x00, 0x01, 0x04, + 0x01, 0x01, 0x01, 0x01, 0x54, 0x14, 0x11, 0x00, 0x10, 0x10, 0x04, 0x04, + 0x04, 0x10, 0x00, 0x14, 0x51, 0x10, 0x44, 0x01, 0x50, 0x44, 0x44, 0x14, + 0xa0, 0x00, 0x02, 0x08, 0x08, 0x80, 0x00, 0x82, 0x00, 0x82, 0x80, 0x00, + 0xa8, 0x28, 0x00, 0xa0, 0x0a, 0x20, 0x08, 0x02, 0x08, 0x08, 0x00, 0x00, + 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x05, 0x04, 0x00, + 0x10, 0x00, 0x55, 0x45, 0x55, 0x41, 0x40, 0x00, 0x54, 0x54, 0x00, 0x50, + 0x05, 0x10, 0x04, 0x55, 0x05, 0x04, 0x00, 0x44, 0x10, 0x14, 0x45, 0x04, + 0x10, 0x54, 0x54, 0x04, 0x00, 0x0a, 0x02, 0x00, 0x08, 0x80, 0xaa, 0x82, + 0xaa, 0x82, 0x80, 0x00, 0x2a, 0xaa, 0x00, 0x08, 0x08, 0x20, 0x02, 0xaa, + 0x0a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x10, 0x14, 0x04, 0x00, 0x04, 0x00, 0x01, 0x40, 0x00, 0x40, 0x40, 0x00, + 0x15, 0x45, 0x15, 0x04, 0x04, 0x10, 0x01, 0x01, 0x00, 0x04, 0x00, 0x05, + 0x15, 0x10, 0x44, 0x04, 0x14, 0x14, 0x41, 0x04, 0x08, 0x08, 0x0a, 0x08, + 0x08, 0x80, 0x02, 0x82, 0x80, 0x20, 0x20, 0x80, 0x8a, 0x8a, 0x22, 0x02, + 0x02, 0xa0, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x05, 0x54, 0x15, 0x55, 0x01, 0x55, 0x01, + 0x55, 0x51, 0x51, 0x01, 0x45, 0x05, 0x00, 0x54, 0x15, 0x40, 0x00, 0x54, + 0x45, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0x02, 0xa8, 0x82, 0xaa, 0x00, 0xaa, 0x00, 0x2a, 0xa8, 0xa8, 0x80, + 0x82, 0x22, 0x20, 0xa8, 0x0a, 0x20, 0x00, 0xa8, 0x80, 0xaa, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x55, 0x55, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0xa8, 0xaa, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x2a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x54, 0x55, 0x01, 0x00, 0x40, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x80, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x50, 0x55, 0x05, + 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x0a, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x0a, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, + 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x80, 0xaa, 0x2a, + 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa8, 0x02, 0x08, 0x00, 0x10, 0x50, 0x50, 0x50, 0x40, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x50, 0x00, + 0x50, 0x00, 0x05, 0x04, 0x01, 0x05, 0x50, 0x40, 0x54, 0x05, 0x04, 0x05, + 0x8a, 0x20, 0x20, 0x88, 0xa0, 0x28, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, + 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x20, 0x00, 0x82, 0x82, 0x08, 0x8a, + 0x82, 0x08, 0x88, 0xa0, 0xa8, 0x0a, 0x22, 0x28, 0x00, 0x41, 0x00, 0x04, + 0x41, 0x44, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x55, 0x55, + 0x00, 0x00, 0x10, 0x00, 0x01, 0x41, 0x10, 0x44, 0x44, 0x10, 0x04, 0x41, + 0x50, 0x15, 0x11, 0x10, 0x80, 0x80, 0x00, 0x02, 0x82, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x80, 0x00, + 0x02, 0x22, 0x20, 0x08, 0x20, 0x20, 0x02, 0x22, 0xa0, 0x2a, 0x22, 0x20, + 0x00, 0x41, 0x10, 0x01, 0x44, 0x00, 0x00, 0x40, 0x41, 0x51, 0x04, 0x14, + 0x15, 0x00, 0x11, 0x44, 0x50, 0x54, 0x40, 0x01, 0x05, 0x10, 0x00, 0x04, + 0x10, 0x40, 0x01, 0x44, 0x10, 0x15, 0x51, 0x00, 0xa8, 0x80, 0x00, 0xaa, + 0x82, 0x00, 0x00, 0x20, 0x22, 0x8a, 0xa2, 0x22, 0x22, 0x80, 0xa0, 0x88, + 0x88, 0x88, 0x88, 0x02, 0x2a, 0x20, 0x00, 0x08, 0xa0, 0x2a, 0xaa, 0x22, + 0x20, 0x8a, 0xa0, 0x02, 0x04, 0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x40, + 0x10, 0x10, 0x41, 0x54, 0x11, 0x00, 0x11, 0x40, 0x54, 0x05, 0x04, 0x05, + 0x50, 0x11, 0x00, 0x04, 0x10, 0x00, 0x01, 0x40, 0x10, 0x45, 0x00, 0x15, + 0x82, 0x80, 0x08, 0x02, 0x80, 0x00, 0x00, 0x00, 0x22, 0x88, 0x02, 0x02, + 0x22, 0x00, 0x82, 0x08, 0x02, 0x08, 0x02, 0x0a, 0x80, 0x22, 0x00, 0x08, + 0x20, 0x00, 0x02, 0x20, 0x20, 0xa2, 0x00, 0x28, 0x01, 0x01, 0x05, 0x01, + 0x40, 0x00, 0x00, 0x40, 0x14, 0x51, 0x41, 0x44, 0x11, 0x40, 0x04, 0x11, + 0x04, 0x05, 0x01, 0x14, 0x00, 0x15, 0x00, 0x04, 0x10, 0x00, 0x01, 0x40, + 0x10, 0x51, 0x01, 0x50, 0x82, 0x00, 0x02, 0x02, 0x80, 0x00, 0x00, 0x80, + 0xa2, 0x88, 0x2a, 0x28, 0x22, 0x80, 0x02, 0x28, 0x8a, 0x88, 0x00, 0x28, + 0x00, 0x22, 0x00, 0x08, 0x20, 0x00, 0x02, 0x20, 0xa0, 0xa8, 0x02, 0x20, + 0x01, 0x05, 0x05, 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, + 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x01, 0x44, 0x00, 0x04, + 0x40, 0x40, 0x04, 0x44, 0x10, 0x51, 0x15, 0x40, 0x82, 0x00, 0x02, 0x08, + 0x82, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, + 0x2a, 0x00, 0x00, 0x00, 0x02, 0x82, 0x08, 0x08, 0x80, 0x20, 0x08, 0x22, + 0xa0, 0xa0, 0x2a, 0x20, 0x14, 0x01, 0x00, 0x50, 0x50, 0x01, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x05, 0x15, 0x00, 0x05, 0x50, 0x50, 0x50, 0x40, 0x15, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x2a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x54, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa0, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x55, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x2a, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xaa, 0x15, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, + 0xa2, 0x00, 0x80, 0x02, 0x0a, 0xa2, 0x82, 0x02, 0x0a, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xa8, 0xa0, 0x80, 0x82, 0xa0, 0x11, 0x01, 0x00, 0x04, + 0x11, 0x50, 0x41, 0x04, 0x11, 0x10, 0x00, 0x14, 0x44, 0x40, 0x00, 0x41, + 0x11, 0x00, 0x14, 0x00, 0x44, 0x05, 0x05, 0x04, 0x45, 0x00, 0x10, 0x44, + 0x11, 0x11, 0x04, 0x44, 0xa2, 0x02, 0x20, 0x80, 0x20, 0x28, 0x20, 0x08, + 0x02, 0x20, 0x80, 0x22, 0xa8, 0xa8, 0xa0, 0x82, 0x28, 0x00, 0x28, 0x80, + 0x22, 0x08, 0x82, 0x0a, 0x22, 0x80, 0x00, 0x82, 0x20, 0x00, 0x88, 0x8a, + 0x51, 0x05, 0x50, 0x00, 0x10, 0x11, 0x11, 0x10, 0x01, 0x50, 0x40, 0x10, + 0x54, 0x04, 0x11, 0x04, 0x41, 0x00, 0x50, 0x40, 0x10, 0x04, 0x44, 0x10, + 0x44, 0x40, 0x01, 0x01, 0x10, 0x10, 0x44, 0x14, 0xa2, 0x00, 0xa0, 0x00, + 0xa8, 0x02, 0xa0, 0x0a, 0x02, 0xa0, 0xa0, 0x00, 0x0a, 0x82, 0x08, 0x82, + 0x20, 0x00, 0xa0, 0x20, 0x20, 0x08, 0x22, 0x08, 0x02, 0x80, 0x02, 0x02, + 0x20, 0xa8, 0x8a, 0x82, 0x51, 0x01, 0x40, 0x01, 0x55, 0x01, 0x10, 0x00, + 0x01, 0x40, 0x41, 0x00, 0x04, 0x54, 0x50, 0x41, 0x40, 0x00, 0x40, 0x10, + 0x10, 0x04, 0x41, 0x05, 0x01, 0x00, 0x05, 0x01, 0x10, 0x10, 0x40, 0x50, + 0xa2, 0x08, 0x80, 0x82, 0xa0, 0x8a, 0x20, 0x00, 0x02, 0x80, 0x22, 0x00, + 0x02, 0x0a, 0x28, 0x80, 0x20, 0x00, 0x80, 0x20, 0x08, 0x88, 0xa0, 0x00, + 0x02, 0x00, 0x0a, 0x02, 0x20, 0x08, 0x80, 0xa0, 0x51, 0x01, 0x00, 0x44, + 0x50, 0x11, 0x10, 0x00, 0x01, 0x00, 0x11, 0x00, 0x01, 0x01, 0x04, 0x40, + 0x10, 0x00, 0x40, 0x11, 0x10, 0x10, 0x11, 0x00, 0x01, 0x00, 0x10, 0x01, + 0x10, 0x10, 0x40, 0x50, 0xa2, 0x08, 0x00, 0x88, 0x80, 0x08, 0x20, 0x00, + 0x02, 0x02, 0x22, 0x00, 0x02, 0x02, 0x08, 0x20, 0x20, 0x00, 0x80, 0x08, + 0x08, 0x88, 0x20, 0x80, 0x00, 0x00, 0x20, 0x02, 0x20, 0x28, 0x80, 0xa0, + 0x51, 0x11, 0x10, 0x44, 0x40, 0x50, 0x40, 0x10, 0x01, 0x00, 0x11, 0x00, + 0x01, 0x01, 0x04, 0x40, 0x10, 0x00, 0x01, 0x11, 0x04, 0x50, 0x10, 0x00, + 0x01, 0x40, 0x10, 0x04, 0x11, 0x50, 0x00, 0x01, 0xa2, 0x28, 0x20, 0x82, + 0x0a, 0x20, 0xa0, 0x0a, 0x02, 0x02, 0x22, 0x88, 0x00, 0x82, 0x08, 0x22, + 0x08, 0x80, 0x80, 0x28, 0x08, 0x28, 0x20, 0x88, 0x00, 0x80, 0x08, 0xaa, + 0x20, 0xa0, 0x82, 0xaa, 0x41, 0x50, 0x50, 0x01, 0x55, 0x00, 0x00, 0x05, + 0x05, 0x05, 0x51, 0x04, 0x01, 0x45, 0x14, 0x11, 0x50, 0x00, 0x41, 0x50, + 0x04, 0x10, 0x50, 0x44, 0x00, 0x40, 0x05, 0x50, 0x50, 0x40, 0x01, 0x14, + 0xaa, 0xaa, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa0, 0x82, + 0x00, 0x2a, 0xa8, 0x20, 0x28, 0x80, 0x2a, 0x20, 0x08, 0x08, 0xa0, 0x82, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x80, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x55, 0x01, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0xa0, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa0, 0xaa, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x55, 0x55, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x2a, 0x2a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xaa, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x45, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0xa2, 0x22, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x88, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x0a, 0x00, 0x0a, 0x08, + 0x02, 0x22, 0xa0, 0x80, 0x08, 0x00, 0xa0, 0x00, 0x20, 0xa0, 0xa0, 0xa0, + 0x41, 0x01, 0x51, 0x45, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, + 0x00, 0x00, 0x55, 0x55, 0x14, 0x00, 0x11, 0x14, 0x05, 0x45, 0x10, 0x41, + 0x11, 0x00, 0x40, 0x01, 0x14, 0x41, 0x40, 0x10, 0x82, 0x28, 0xa2, 0xaa, + 0x80, 0xa2, 0xa2, 0xa0, 0xa8, 0x00, 0x28, 0x28, 0x08, 0xa2, 0x02, 0xaa, + 0xa8, 0x80, 0x20, 0x88, 0x88, 0x0a, 0x08, 0x82, 0x20, 0x00, 0x80, 0x0a, + 0x00, 0x82, 0x00, 0x08, 0x04, 0x51, 0x51, 0x55, 0x45, 0x44, 0x11, 0x11, + 0x11, 0x01, 0x50, 0x44, 0x04, 0x11, 0x05, 0x55, 0x41, 0x41, 0x40, 0x10, + 0x40, 0x55, 0x04, 0x44, 0x40, 0x00, 0x00, 0x14, 0x00, 0x01, 0x01, 0x04, + 0x88, 0xa8, 0xa8, 0x2a, 0x2a, 0x20, 0x08, 0x0a, 0x0a, 0x02, 0xa0, 0x80, + 0x88, 0x08, 0xa2, 0xaa, 0x02, 0x22, 0x00, 0x08, 0xa0, 0x8a, 0x02, 0x88, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x82, 0x20, 0x02, 0x05, 0x55, 0x54, 0x55, + 0x44, 0x40, 0x50, 0x51, 0x11, 0x01, 0x04, 0x51, 0x10, 0x51, 0x41, 0x55, + 0x05, 0x44, 0x00, 0x10, 0x00, 0x50, 0x54, 0x45, 0x40, 0x00, 0x00, 0x40, + 0x50, 0x01, 0x01, 0x54, 0x80, 0x2a, 0xaa, 0x0a, 0x28, 0x28, 0x08, 0x08, + 0x08, 0x02, 0x88, 0x88, 0x80, 0x08, 0xa8, 0xaa, 0x0a, 0x28, 0x00, 0x08, + 0xa0, 0x02, 0x02, 0x80, 0x20, 0x00, 0x00, 0x80, 0x08, 0x02, 0x02, 0x02, + 0x00, 0x15, 0x55, 0x15, 0x44, 0x44, 0x10, 0x11, 0x11, 0x01, 0x04, 0x45, + 0x50, 0x10, 0x51, 0x55, 0x15, 0x44, 0x00, 0x10, 0x00, 0x01, 0x04, 0x40, + 0x40, 0x00, 0x00, 0x40, 0x04, 0x01, 0x11, 0x04, 0x80, 0x0a, 0xaa, 0x2a, + 0x82, 0x22, 0xa0, 0xa0, 0x08, 0x02, 0xa8, 0xa8, 0x20, 0xa0, 0xa8, 0xaa, + 0x0a, 0x28, 0x00, 0x08, 0x80, 0x00, 0x02, 0x80, 0x20, 0x00, 0x00, 0x80, + 0x02, 0x02, 0x0a, 0x02, 0x00, 0x04, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x44, 0x00, 0x10, + 0x10, 0x00, 0x04, 0x40, 0x40, 0x00, 0x00, 0x40, 0x04, 0x01, 0x04, 0x04, + 0x08, 0x02, 0xa8, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xaa, 0x28, 0x82, 0x00, 0x08, 0xa8, 0x80, 0x08, 0x88, + 0x20, 0x00, 0x20, 0x20, 0x02, 0x0a, 0x0a, 0x08, 0x44, 0x00, 0x50, 0x55, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + 0x51, 0x01, 0x11, 0x10, 0x54, 0x41, 0x10, 0x44, 0x40, 0x00, 0x40, 0x10, + 0x04, 0x01, 0x04, 0x10, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0xa0, 0x00, 0x08, 0x00, 0x00, 0x00, 0xaa, 0x08, 0x00, 0x0a, 0x2a, + 0x2a, 0x0a, 0xa0, 0xa0, 0xa0, 0x00, 0x20, 0x0a, 0x28, 0x02, 0x00, 0xa0, + 0x50, 0x01, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -- cgit v1.2.3