aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs')
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Agent.h130
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Args.c2380
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Args.h86
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Atoms.c788
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Atoms.h65
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Binder.c177
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Binder.h27
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/CHANGELOG6326
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/COPYING339
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Client.c526
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Client.h119
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Clipboard.c1631
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Clipboard.h61
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Colormap.c588
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Colormap.h84
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Composite.c209
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Composite.h51
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Cursor.c577
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Cursor.h106
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Dialog.c563
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Dialog.h223
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Display.c2752
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Display.h179
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Drawable.c3267
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Drawable.h221
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Error.c636
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Error.h37
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Events.c4739
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Events.h230
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Extensions.c321
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Extensions.h35
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Font.c1876
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Font.h77
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GC.c1712
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GCOps.c2100
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GCOps.h105
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GCs.h111
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Handlers.c1311
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Handlers.h121
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Holder.c226
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Holder.h27
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Icons.h29
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Image.c1821
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Image.h108
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Imakefile222
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Init.c518
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Init.h42
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keyboard.c1814
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keyboard.h118
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keystroke.c343
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keystroke.h27
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/LICENSE26
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Literals.h205
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Millis.c70
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Millis.h30
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXcomposite.c359
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXcomposite.h86
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h55
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXcompositeint.h76
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXcompositeproto.h148
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdamage.c5
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c4716
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.NX.original4716
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c.XF86.original4110
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c2883
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.NX.original2883
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c.XF86.original2223
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXevents.c4797
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXevents.c.NX.original4797
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXevents.c.XF86.original4637
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXextension.c528
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXextension.c.NX.original528
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXextension.c.XF86.original486
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglxext.c550
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.NX.original550
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglxext.c.XF86.original489
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyph.c511
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.NX.original511
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyph.c.XF86.original416
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c252
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.NX.original252
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c.XF86.original197
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h161
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.NX.original161
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphstr.h.XF86.original127
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c938
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.NX.original938
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c.XF86.original873
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c322
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.NX.original322
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiglyph.c.XF86.original239
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c204
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.NX.original204
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c.XF86.original196
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c1205
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.NX.original1205
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiwindow.c.XF86.original1176
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicture.c1512
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.NX.original1512
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicture.c.XF86.original1305
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h533
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.NX.original533
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicturestr.h.XF86.original501
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXproperty.c921
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.NX.original921
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXproperty.c.XF86.original736
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXrender.c3048
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXrender.c.NX.original3048
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXrender.c.XF86.original2584
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXresource.c1103
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXresource.c.NX.original1103
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXresource.c.XF86.original975
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXshm.c1425
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXshm.c.NX.original1425
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXshm.c.XF86.original1257
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXwindow.c4179
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.NX.original4179
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXwindow.c.XF86.original3947
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXxrandr.c755
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXxrandr.h168
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXxrandrint.h104
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c2277
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.NX.original2277
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c.XF86.original2214
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Options.c191
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Options.h417
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixels.c384
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixels.h180
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixmap.c1646
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h136
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pointer.c191
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pointer.h54
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Reconnect.c812
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Reconnect.h68
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Render.c3062
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Render.h110
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Rootless.c1248
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Rootless.h93
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Screen.c4230
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Screen.h137
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Splash.c335
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Splash.h45
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Split.c1248
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Split.h84
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/TestExt.c83
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Trap.c114
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Trap.h116
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Utils.h39
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Visual.c159
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Visual.h73
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Window.c3876
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Windows.h320
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c2073
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.NX.original2073
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.X.original1966
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c4679
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.NX.original4679
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original4035
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c2805
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.NX.original2804
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original2150
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c5044
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.NX.original5044
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.X.original4670
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c508
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.NX.original508
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.X.original474
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c575
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.NX.original575
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.X.original505
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c581
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.NX.original581
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.X.original488
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c241
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.NX.original241
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.X.original194
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h174
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.NX.original174
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.X.original148
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c979
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.NX.original979
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.X.original905
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c318
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.NX.original318
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.X.original243
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c233
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.NX.original233
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.X.original190
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c1222
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.NX.original1222
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.X.original1184
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c2270
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.NX.original2270
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.X.original1864
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h678
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.NX.original678
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.X.original654
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c992
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.NX.original992
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.X.original729
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c3861
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.NX.original3861
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.X.original3316
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c1250
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.NX.original1250
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original954
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c1498
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.NX.original1498
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.X.original1310
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c4167
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.NX.original4167
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.X.original3853
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c2286
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.NX.original2286
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.X.original2217
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm41
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm48
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/os2Stub.c402
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/screensaver703
-rw-r--r--nx-X11/programs/nxauth/CHANGELOG108
-rw-r--r--nx-X11/programs/nxauth/COPYING339
-rw-r--r--nx-X11/programs/nxauth/Imakefile38
-rw-r--r--nx-X11/programs/nxauth/LICENSE26
-rw-r--r--nx-X11/programs/nxauth/gethost.c287
-rw-r--r--nx-X11/programs/nxauth/nxauth.man236
-rw-r--r--nx-X11/programs/nxauth/parsedpy.c259
-rw-r--r--nx-X11/programs/nxauth/process.c1872
-rw-r--r--nx-X11/programs/nxauth/xauth.c184
-rw-r--r--nx-X11/programs/nxauth/xauth.h58
229 files changed, 264054 insertions, 0 deletions
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..dbed1e0d8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Agent.h
@@ -0,0 +1,130 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..ecf0a21af
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Args.c
@@ -0,0 +1,2380 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef __sun
+#include <strings.h>
+#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;
+
+int nxagentRemoteMajor = -1;
+
+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);
+
+ nxagentChangeOption(AllScreens, True);
+ }
+ else if (!strcmp(argv[i],"ipaq"))
+ {
+ nxagentChangeOption(Fullscreen, True);
+
+ nxagentChangeOption(AllScreens, 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);
+
+ nxagentChangeOption(AllScreens, True);
+ }
+ else if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(Fullscreen, False);
+
+ nxagentChangeOption(AllScreens, 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 (nxagentOption(DesktopResize) == 0 || strcmp(value, "0") == 0)
+ {
+ nxagentResizeDesktopAtStartup = 0;
+ }
+ else if (strcmp(value, "1") == 0)
+ {
+ nxagentResizeDesktopAtStartup = 1;
+ }
+ 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, "macosx") == 0)
+ {
+ nxagentChangeOption(ClientOs, ClientOsMac);
+ }
+
+ return;
+ }
+ else if (strcmp(name, "copysize") == 0)
+ {
+ nxagentChangeOption(CopyBufferSize, atoi(value));
+
+ 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;
+ }
+
+ nxagentRemoteMajor = remoteMajor;
+
+ 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(AllScreens) == UNDEFINED)
+ {
+ nxagentChangeOption(AllScreens, 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 = 4096;
+ tileHeight = 4096;
+
+ break;
+ }
+ case LINK_TYPE_WAN:
+ {
+ deferLevel = 1;
+
+ deferTimeout = 200;
+
+ tileWidth = 4096;
+ tileHeight = 4096;
+
+ break;
+ }
+ case LINK_TYPE_NONE:
+ case LINK_TYPE_LAN:
+ {
+ deferLevel = 0;
+
+ deferTimeout = 200;
+
+ tileWidth = 4096;
+ tileHeight = 4096;
+
+ 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..8f4d05d6c
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Args.h
@@ -0,0 +1,86 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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;
+
+extern int nxagentRemoteMajor;
+
+#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..578731f07
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c
@@ -0,0 +1,788 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 */
+ "UTF8_STRING", /* 12 */
+ "_NET_WM_STATE", /* 13 */
+ "_NET_WM_STATE_FULLSCREEN", /* 14 */
+ 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..d5b7fe5aa
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h
@@ -0,0 +1,65 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifndef __Atoms_H__
+#define __Atoms_H__
+
+#include "X.h"
+#include "../../include/window.h"
+#include "screenint.h"
+
+#define NXAGENT_NUMBER_OF_ATOMS 16
+
+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..d40aaebe6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Binder.c
@@ -0,0 +1,177 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#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..f28a82b9f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Binder.h
@@ -0,0 +1,27 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..0f20b79c3
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/CHANGELOG
@@ -0,0 +1,6326 @@
+ChangeLog:
+
+nxagent-3.5.0-5
+
+- The NX agent failed to resize its own window to fit the desktop size
+ in shadow sessions. TR07I02561 is now fixed also in shadow mode.
+
+nxagent-3.5.0-4
+
+- Fixed TR07I02530. Solved a buffer overflow occurring when the '-fp'
+ option value exceeds 1024 characters.
+
+- Extended list of the available screen geometries.
+
+nxagent-3.5.0-3
+
+- Fixed TR08I02572. Upgraded RandR extension to version 1.2.
+
+- Fixed TR07I02561. The NX agent failed to resize its own window to
+ fit the desktop size.
+
+nxagent-3.5.0-2
+
+- Fixed TR0502449. Initialized font server path even if font server
+ connection fails.
+
+nxagent-3.5.0-1
+
+- Opened the 3.5.0 branch based on nxagent-3.4.0-16.
+
+- Updated copyright to year 2009.
+
+- Fixed TR0302438. Added a check in function exporting property in
+ order to handle the case looking up an atom name returns a null
+ pointer.
+
+nxagent-3.4.0-16
+
+- Updated copyright to year 2011.
+
+nxagent-3.4.0-15
+
+- Added reference to fixed TR11H02405.
+
+nxagent-3.4.0-14
+
+- Reverted fix for TR03H02335 implemented in nxagent-3.4.0-6. The
+ emulation of right click by Control key + left click introduces
+ issues for some applications changing the reaction to the left click
+ depending on the state of Control key. Issue reported in TR03H02335
+ affects Apple laptop touchpads having a single button acting as
+ left button: on those devices the right button can be emulated by
+ a double-fingered tap (using two fingertips simultaneously).
+
+nxagent-3.4.0-13
+
+- Fixed TR12H02414. Exported property must be split if ChangeProperty
+ request exceeds 262140 bytes.
+
+- Reset AllScreens option at reconnection time if full screen mode
+ have to be automatically turned off.
+
+nxagent-3.4.0-12
+
+- If one of the two full screen modes is active ('one screen' or 'all
+ screens') both keystrokes Ctrl-Alt-F and Ctrl-Alt-Shift-F change the
+ mode back to 'windowed'.
+
+- Fixed TR11H02405. XRenderFreePicture is called only for pictures
+ that were actually created on the X server side.
+
+- Ctrl+Alt+f switch fullscreen to all monitors, while Ctrl+Alt+Shift+f
+ does it to one monitor only.
+
+- If the fullscreen option is enabled at the startup, session starts
+ in the fullscreen mode on all monitors.
+
+- Added a call to XReparentWindow in the nxagentSwitchAllScreens().
+
+- Corrected focus and grab when switching to fullscreen on
+ all monitors.
+
+- Removed a compile warning e deleted some unused variables.
+
+- Removed nxagentPointerAndKeyboardGrabbed variable.
+
+- Use the override redirect attribute to switch to fullscreen to all
+ monitors instead of send _NET_WM_FULLSCREEN_MONITORS hint to the WM.
+
+- Added nxagentMinimizeFromFullScreen(), nxagentMaximizeToFullScreen()
+ and nxagentCreateIconWindow().
+
+- Removed check on EnterNotify to grab the keyboard in fullscreen
+ mode not only if mode is 'NotifyNormal'.
+
+nxagent-3.4.0-11
+
+- Corrected switching between viewport mode and resize mode.
+
+- Fixed TR04H02340. Keycode is correctly translated in shadow sessions
+ also if the remote X display is using evdev.
+
+nxagent-3.4.0-10
+
+- Handled XGrabKeyboard() return value.
+
+- Fixed TR10D01512. NumLock and CapsLock keys are now synchronized
+ between local and remote.
+
+nxagent-3.4.0-9
+
+- Fixed TR06H02362. No icon was swown in the task bar.
+
+- Fixed keyboard grab in fullscreen mode.
+
+- Fixed compiler warnings.
+
+nxagent-3.4.0-8
+
+- Grab the keyboard in fullscreen mode on EnterNotify only if mode is
+ 'NotifyNormal'.
+
+- Yield control in the dispatch loop in case we stop the smart sche-
+ duler timer while waiting for a reply from the remote display.
+
+nxagent-3.4.0-7
+
+- Fixed TR08D01478. The communication with the compiz window manager
+ by means of the _NET_WM_PING property was not handled properly.
+
+- Fixed a type mismatch in XKB events on 64 bit platforms.
+
+- Moved grab/ungrab keyboard from focus in/out event to enter/leave
+ notify event.
+
+- Removed nxagentIconWindow because it's not longer used.
+
+nxagent-3.4.0-6
+
+- Fixed TR09F02102. Problem was with pointer buttons map.
+
+- Fixed TR02H02327. Some KeyRelease events was discarded.
+
+- Fixed up Num and Caps locks.
+
+- Fixed TR03H02335. Emulated right mouse button for Mac clients.
+
+- Added utilities to print info about internal and remote windows.
+
+- Fixed TR01F01995. Solved a picture resource leak by destroying remo-
+ te pictures only when their reference counter returns to zero.
+
+- Fixed TR04H02337. Errors occurred because pictures with no drawable
+ were handled badly.
+
+- Implemented handling nxagent's private for gradient pictures and so-
+ lid fill picture.
+
+- Fixed BadMatch condition check in function ProcRenderComposite.
+
+- Fixed nxagentComposite() to handle situations with source picture
+ drawable pointing to NULL.
+
+- Implemented render acceleration for requests: CreateSolidFill,
+ CreateLinearGradient, CreateRadialGradient, CreateConicalGradient.
+
+- Fixed TR03G02196. Dialogs are shown to the fore when the NX session
+ is in fullscreen mode.
+
+- Changed mechanism to switch to fullscreen mode. Now the override
+ redirect attribute is no longer used and _NET_WM_STATE_FULLSCREEN
+ hint is sent to the WM.
+
+nxagent-3.4.0-5
+
+- Updated copyright to year 2010.
+
+nxagent-3.4.0-4
+
+- Fixed TR07F02090. Now XDMCP sessions start without problems.
+
+- Fixed TR08G02259. Corrected window border granularity of rootless
+ session at reconnection on 64 bit platforms.
+
+- Fixed TR11G02290. Forcing null timeout with queued events only if
+ display connection is up. This prevents the flood of session log.
+
+- Fixed TR10G02287. Now QueryTree's loop is aborted in case of failure
+ and session log isn't filled anymore with repeated warning messages.
+
+- Fixed TR01G02154. Corrected window placement when switching between
+ fullscreen and windowed mode.
+
+- Fixed TR09G02276. Now the agent does not receive unwanted characters
+ while interacting with the local window manager.
+
+- Implemented FR02G02174. Added ability to do large screen pans in
+ viewport mode through key combination Ctrl+Alt+Shift+Arrow.
+
+- Corrected parsing of the 'client' option when the client OS is Mac.
+
+nxagent-3.4.0-3
+
+- Fixed TR09G02271. The array containing the font name fields was not
+ correctly initialized for non-standard font names.
+
+nxagent-3.4.0-2
+
+- Updated copyright to year 2009.
+
+nxagent-3.4.0-1
+
+- Opened the 3.4.0 branch based on nxagent-3.3.0-19.
+
+- Changed the printed version number.
+
+nxagent-3.3.0-19
+
+- Fixed TR09G02266. A proper error message is printed in the session
+ log if the shadowing initialization fails because of a mismatch in
+ the visual class.
+
+- Added a workaround for X servers that doesn't return 1 among the
+ available depths.
+
+nxagent-3.3.0-18
+
+- The area to restore from the backing store is limited by the screen
+ size instead of the visible screen.
+
+nxagent-3.3.0-17
+
+- Fixed TR12F02150. The agent could crash when copying text from VNC
+ viewer. Fixed by aborting the procedure in case the retrieved pro-
+ perty has not a valid format.
+
+nxagent-3.3.0-16
+
+- Fixed TR07G02247. Don't try to call XSetWindowColormap() if the
+ window has no colormap, e.g. if its class is InputOnly.
+
+nxagent-3.3.0-15
+
+- Fixed TR04G02210. Region is cut to the visible screen before re-
+ storing areas from the backing store.
+
+- Fixed TR07G02246. Box is shrinked if bounds can't stay in a short
+ signed integer.
+
+nxagent-3.3.0-14
+
+- Fixed TR03G02206. waitpid() call was missing for the "Fonts replace-
+ ment" dialog type.
+
+- Fixed TR03G02195. Added a properties structure compatible with 32
+ and 64 bit platform types.
+
+nxagent-3.3.0-13
+
+- Handle the window unmap immediately. Don't add it to the configure
+ queue.
+
+nxagent-3.3.0-12
+
+- Fixed TR03G02200. Timestamps could be in the future in KeyRelease
+ events sent to the X clients.
+
+- Added debug logging of input devices state Logging can be enabled
+ or disabled via the Ctrl+Alt+x shortcut. State info is dumped every
+ 5 seconds.
+
+- Added Ctrl+Alt+y shortcut used to deactivate input devices grab for
+ debug purposes.
+
+nxagent-3.3.0-11
+
+- Changed the message logging the screen size changes, in order to
+ show the fullscreen state.
+
+- Handle the window unmapping in the nxagentConfigureWindow queue.
+
+nxagent-3.3.0-10
+
+- Fixed TR12F02146. Compare the drawable and the bitmap data before
+ realizing the image update, in order to delay the data clean up that
+ caused the memcmp() failure.
+
+- Fixed TR01G02156. Reduce the exposing area by subtracting the ex-
+ posed region.
+
+- Fixed a compile warning in Drawable.c.
+
+- Added detailed logs in the nxagentSynchronizeRegion() function if
+ the data memory allocation fails.
+
+nxagent-3.3.0-9
+
+- Added /usr/NX/share/base to alternate font paths. This would fix
+ TR11F02130 if fonts fixed and cursor are installed there.
+
+- Changed Keyboard initialization and reset. This change should fix
+ TR11F02129, TR11F02131, TR11F02132.
+
+nxagent-3.3.0-8
+
+- Fixed TR12F02144. Image bits of render glyphs are copied before they
+ are cleaned. This will avoid a memory corruption.
+
+- Fixed TR12F02145. When dispatching a MotionNotify event, check if a
+ top-level window has been entered before trying to show the pulldown
+ dialog.
+
+nxagent-3.3.0-7
+
+- Added debug code for pointer input.
+
+nxagent-3.3.0-6
+
+- Fixed compile warnings.
+
+nxagent-3.3.0-5
+
+- Disabled verbose logging in Rootless.c.
+
+nxagent-3.3.0-4
+
+- Fix the XKB map load in the case of 64 bit server.
+
+nxagent-3.3.0-3
+
+- Fixed TR10F02119. If the remote X display is using evdev keyboard
+ then copy maps from remote.
+
+- Upgraded VERSION to 3.3.0.
+
+nxagent-3.3.0-2
+
+- Fixed TR10F02115. Painting errors occurred when screen areas beyond
+ the current viewport became viewable in the NX Client for Windows.
+
+- Using a new struct type nxagentWMHints to avoid type mismatch on
+ 64 bit platforms.
+
+- Added debug utilities for pointer input.
+
+nxagent-3.3.0-1
+
+- Opened the 3.3.0 branch based on nxagent-3.2.0-12.
+
+nxagent-3.2.0-12
+
+- Ignore 'resize' option at reconnection if viewport mode is on.
+
+- Fixed TR08E01814. Added shadow keymap initialization in order to
+ enable nxcompshad to translate keycodes across different layouts.
+
+nxagent-3.2.0-11
+
+- Fixed TR08F02098. Function splitting font names has to be instruct-
+ ed to handle the right number of fields.
+
+nxagent-3.2.0-10
+
+- Extended fix for TR07F02091 to include font names having zero in
+ fields RESOLUTION_X and RESOLUTION_Y.
+
+nxagent-3.2.0-9
+
+- Fixed TR07F02091. Scalable fonts were not correctly listed among
+ available fonts.
+
+- Fixed TR06F02080. Use the corrupted area extents as maximum size of
+ the image data.
+
+nxagent-3.2.0-8
+
+- Fixed TR07F02082. The agent server could be unable to init core
+ keyboard on 64 bit systems.
+
+nxagent-3.2.0-7
+
+- Imported patch fixing issues from X.Org security advisory, June
+ 11th, 2008: Multiple vulnerabilities in X server extensions. CVE
+ IDs: CVE-2008-1377, CVE-2008-1379, CVE-2008-2360, CVE-2008-2361,
+ CVE-2008-2362.
+
+nxagent-3.2.0-6
+
+- Fixed TR05F02063. Ignore ReparentNotify events for non-rootless
+ sessions.
+
+- Fixed TR06F02068. Try to pack images only if format is ZPixmap.
+
+- Don't require reparent on close of NX window.
+
+nxagent-3.2.0-5
+
+- Fixed TR04F02044. Restored the original MakeRootTile() function in
+ order to create the root window background pixmap.
+
+- Fixed TR04F02041. Gnome panels stayed on top of the NX session win-
+ dow with desktops running Compiz. This fix provides a solution for
+ the Fullscreen mode.
+
+- Improved for the shadow session the handling of master session win-
+ dow resize.
+
+nxagent-3.2.0-4
+
+- Fixed TR10D01535. The agent window is not minimized anymore when
+ pointer leaves.
+
+- Changes aimed to avoid possible type mismatch in XDisplay struct
+ on 64 bit architectures.
+
+nxagent-3.2.0-3
+
+- Fixed a build issue on Solaris.
+
+nxagent-3.2.0-2
+
+- Code clean up. Moved a variable definition to the beginnning of a
+ block.
+
+nxagent-3.2.0-1
+
+- Opened the 3.2.0 branch based on nxagent-3.1.0-9.
+
+nxagent-3.1.0-9
+
+- Fixed TR03F02025. German umlauts couldn't be pasted into a remote
+ Windows application. Now also the UTF8_STRING target is available
+ for ConvertSelection requests.
+
+- Fixed TR03F02031. Moved SetScreenSaverTimer() call in order to avoid
+ undesired reset of the auto-disconnect timeout when a screen saver
+ turns on.
+
+nxagent-3.1.0-8
+
+- Added reference to fixed TR02F02007 and TR07E01762 in the CHANGELOG.
+
+- Set the GC trap before calling fbPolySegment.
+
+- Fixed TR09E01863. A flag is set if a resource has been added or fre-
+ ed and it is checked in FindClientResourcesByType().
+
+- Added void entries to nxagentRequestLiteral vector in order to avoid
+ a wrong string is printed to the output for NoOperation request.
+
+- Fixed TR11E01948. Now keyboard status is initialized again after
+ the NX session is reconnected. This avoids CAPS LOCK and NUM LOCK
+ synchronization problems.
+
+- Added nxagentXkbCapsTrap and nxagentXkbNumTrap to avoid CAPS LOCK
+ and NUM LOCK synchronization problems when CAPS LOCK or NUM LOCK is
+ the first key to be pressed in the NX session.
+
+- Corrected subSize variable initialization in nxagentRealizeImage().
+
+- Fixed various memory leaks.
+
+- Fixed TR11E01950. Copy and paste via edit menu didn't work for some
+ applications.
+
+- Corrected property type in nxagentRequestSelection(). Some external
+ applications didn't enable their paste button when nxagent was the
+ owner of the CLIPBOARD selection.
+
+- Added struct to save values queried by XQueryExtension for XFixes
+ extension.
+
+nxagent-3.1.0-7
+
+- Imported patch fixing issues from X.Org security advisory, January
+ 17th, 2008: Multiple vulnerabilities in the X server. CVE IDs:
+ CVE-2007-5760 CVE-2007-5958 CVE-2007-6427 CVE-2007-6428
+ CVE-2007-6429 CVE-2008-0006.
+
+- Fixed TR02F02007. Handled the case if nxagentCreateDrawableBitmap()
+ fails to create the pixmap intended to store the bitmap data.
+
+nxagent-3.1.0-6
+
+- Fixed a compile warning in Args.c.
+
+- The synchronization loop breaks if the drawable is clean when it's
+ not supposed to be.
+
+- Fixed TR12E01966. Emacs tooltips were not displayed properly. Added
+ a check on the event mask before calling miWindowExposures().
+
+- Fixed TR01F01982. ConfigureNotify warning is printed in verbose mode
+ only.
+
+nxagent-3.1.0-5
+
+- Moved some variable definitions placed in ProcGetProperty().
+
+nxagent-3.1.0-4
+
+- Fixed TR06D01397. The problem was: drag & drop operations between
+ windows of Java applications didn't work in NX Client for Windows.
+
+- Implemented FR12E01957. Added a limit to the amount of data that can
+ be pasted from an NX session into an external application. The new
+ option - named 'copysize' - can be read from the 'options' file.
+
+nxagent-3.1.0-3
+
+- Fixed TR12E01963. The window tree is revalidated explicitly after
+ recomputing the root window clip regions.
+
+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 TR07E01762. Problem in comparison of font names.
+
+- 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 [<screen number>] to [<width>x<height>].
+
+- 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-<TAB> 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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..63ed0e134
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Client.c
@@ -0,0 +1,526 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+/*
+ * Used in handling of karma on lost focus.
+ */
+
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#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..a9b06c845
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Client.h
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..2742e147f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c
@@ -0,0 +1,1631 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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"
+
+#include "gcstruct.h"
+#include "xfixeswire.h"
+#include <X11/extensions/Xfixes.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;
+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 serverUTF8_STRING;
+static Atom clientTARGETS;
+static Atom clientTEXT;
+static Atom clientCOMPOUND_TEXT;
+static Atom clientUTF8_STRING;
+
+static char szAgentTARGETS[] = "TARGETS";
+static char szAgentTEXT[] = "TEXT";
+static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT";
+static char szAgentUTF8_STRING[] = "UTF8_STRING";
+static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT";
+
+/*
+ * Save the values queried from X server.
+ */
+
+XFixesAgentInfoRec nxagentXFixesInfo = { -1, -1, -1, 0 };
+
+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,
+ XInternAtom(nxagentDisplay, "ATOM", 0),
+ 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;
+ }
+
+ if (resultFormat != 8 && resultFormat != 16 && resultFormat != 32)
+ {
+
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: WARNING! Invalid property "
+ "value.\n");
+ #endif
+
+ if (lastClientClientPtr != NULL)
+ {
+ 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[4];
+ xEvent x;
+
+ xa_STRING[0] = XA_STRING;
+ xa_STRING[1] = clientTEXT;
+ xa_STRING[2] = clientCOMPOUND_TEXT;
+ xa_STRING[3] = clientUTF8_STRING;
+
+ ChangeWindowProperty(pWin,
+ property,
+ MakeAtom("ATOM", 4, 1),
+ sizeof(Atom)*8,
+ PropModeReplace,
+ 4,
+ &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) ||
+ (target == clientUTF8_STRING))
+ {
+ 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;
+ }
+
+ if (target == clientUTF8_STRING)
+ {
+ XConvertSelection(nxagentDisplay, selection, serverUTF8_STRING, serverCutProperty,
+ serverWindow, CurrentTime);
+ }
+ else
+ {
+ 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 */
+ serverUTF8_STRING = nxagentAtoms[12]; /* UTF8_STRING */
+
+ 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 (XQueryExtension(nxagentDisplay,
+ "XFIXES",
+ &nxagentXFixesInfo.Opcode,
+ &nxagentXFixesInfo.EventBase,
+ &nxagentXFixesInfo.ErrorBase) == 0)
+ {
+ ErrorF("Unable to initialize XFixes extension.\n");
+ }
+
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitClipboard: Registering for XFixesSelectionNotify events.\n");
+ #endif
+
+ XFixesSelectSelectionInput(nxagentDisplay, iWindow, nxagentClipboardAtom,
+ XFixesSetSelectionOwnerNotifyMask |
+ XFixesSelectionWindowDestroyNotifyMask |
+ XFixesSelectionClientCloseNotifyMask);
+
+ nxagentXFixesInfo.Initialized = 1;
+ }
+
+ 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);
+ clientUTF8_STRING = MakeAtom(szAgentUTF8_STRING, strlen(szAgentUTF8_STRING), 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..43189df81
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h
@@ -0,0 +1,61 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifndef __Clipboard_H__
+#define __Clipboard_H__
+
+/*
+ * Queried at clipboard initialization.
+ */
+
+typedef struct _XFixesAgentInfo
+{
+ int Opcode;
+ int EventBase;
+ int ErrorBase;
+ int Initialized;
+
+} XFixesAgentInfoRec;
+
+extern XFixesAgentInfoRec nxagentXFixesInfo;
+
+/*
+ * 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..b0f0507b5
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Colormap.c
@@ -0,0 +1,588 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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);
+
+ if (pCmap != NULL)
+ {
+ XSetWindowColormap(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ nxagentColormap(pCmap));
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "nxagentSetInstalledColormapWindows: WARNING! "
+ "Window at [%p] has no colormap with class [%d].\n",
+ pWin, pWin -> drawable.class);
+ }
+ #endif
+ }
+#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..b2960590c
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Colormap.h
@@ -0,0 +1,84 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..c79104fc1
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Composite.c
@@ -0,0 +1,209 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..e875d0051
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Composite.h
@@ -0,0 +1,51 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..e27415b91
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Cursor.c
@@ -0,0 +1,577 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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)
+{
+ return 1;
+}
+
+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..df7dc44f7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Cursor.h
@@ -0,0 +1,106 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..0fb9491a4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c
@@ -0,0 +1,563 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "scrnintstr.h"
+#include "Agent.h"
+
+#include <X11/Xlib.h>
+
+#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..bd12f3097
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.h
@@ -0,0 +1,223 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 nxagentFontsReplacementDialogPid;
+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..db70434e3
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Display.c
@@ -0,0 +1,2752 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <signal.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#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 = NULL;
+int nxagentNumDefaultColormaps;
+int *nxagentDepths = NULL;
+int nxagentNumDepths;
+XPixmapFormatValues *nxagentPixmapFormats = NULL;
+XPixmapFormatValues *nxagentRemotePixmapFormats = NULL;
+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 && nxagentFontsReplacementDialogPid)
+ {
+ pid = waitpid(nxagentFontsReplacementDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Fonts replacement).\n",
+ nxagentFontsReplacementDialogPid);
+ #endif
+
+ pid = nxagentFontsReplacementDialogPid = 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;
+
+/*
+XXX: Some X server doesn't list 1 among available depths...
+*/
+
+ nxagentPixmapFormats = xalloc((nxagentNumDepths + 1) * sizeof(XPixmapFormatValues));
+
+ for (i = 1; i <= MAXDEPTH; i++)
+ {
+ depth = 0;
+
+ if (i == 1)
+ {
+ depth = 1;
+ }
+ else
+ {
+ 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;
+
+ nxagentRemoteMajor = -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;
+ }
+
+ /*
+ * nxagentPixmapFormats and nxagentRemotePixmapFormats
+ * will be reallocated in nxagentInitPixmapFormats().
+ */
+
+ if (nxagentPixmapFormats != NULL)
+ {
+ XFree(nxagentPixmapFormats);
+
+ nxagentPixmapFormats = NULL;
+ }
+
+ if (nxagentRemotePixmapFormats != NULL)
+ {
+ XFree(nxagentRemotePixmapFormats);
+
+ nxagentRemotePixmapFormats = NULL;
+ }
+
+ /*
+ * 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..454150d6e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Display.h
@@ -0,0 +1,179 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..9c167743f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Drawable.c
@@ -0,0 +1,3267 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 "GCOps.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 extentWidth, extentHeight;
+ 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 at [%p] "
+ "[%d,%d,%d,%d] with [%ld] rects.\n", nxagentDrawableType(pDrawable),
+ (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,
+ 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), nxagentDrawableType(pDrawable), (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
+
+ /*
+ * We are going to synchronize the corrupted
+ * area, so we use the corrupted extents as
+ * maximum size of the image data. It's im-
+ * portant to avoid using the drawable size,
+ * because in case of a huge window it had to
+ * result in a failed data memory allocation.
+ */
+
+ extentWidth = clipRegion -> extents.x2 - clipRegion -> extents.x1;
+ extentHeight = clipRegion -> extents.y2 - clipRegion -> extents.y1;
+
+ w = tileWidth = (nxagentOption(TileWidth) > extentWidth ? extentWidth : nxagentOption(TileWidth));
+ h = tileHeight = (nxagentOption(TileHeight) > extentHeight ? extentHeight : 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");
+
+ /*
+ * Print detailed informations if the
+ * image length is zero.
+ */
+
+ if (length == 0)
+ {
+ fprintf(stderr, "nxagentSynchronizeRegion: Drawable [%s] at [%p] with region geometry [%ld][%d,%d,%d,%d].\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable, REGION_NUM_RECTS(clipRegion),
+ clipRegion -> extents.x1, clipRegion -> extents.y1,
+ clipRegion -> extents.x2, clipRegion -> extents.y2);
+ }
+
+ #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);
+
+ /*
+ * FIXME: This should not occur.
+ */
+
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ #ifdef WARNING
+
+ if (pDrawable -> type == DRAWABLE_WINDOW && pSrcDrawable != pDrawable)
+ {
+ fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Trying to synchronize "
+ "the clean drawable type [%d] at [%p] with source at [%p].\n",
+ pDrawable -> type, (void *) pDrawable, (void *) pSrcDrawable);
+ }
+
+ #endif
+
+ goto nxagentSynchronizeRegionStop;
+ }
+
+ 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);
+
+ /*
+ * 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);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentSynchronizeRegion: Tile [%d,%d,%d,%d] on drawable [%p] doesn't match.\n",
+ x, y, x + w, y + h, (void *) pDrawable);
+ }
+ #endif
+ }
+ 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);
+ }
+ }
+
+ /*
+ * Realize the image after comparing the
+ * source data with the bitmap data.
+ */
+
+ nxagentRealizeImage(pDrawable, pGC, pDrawable -> depth,
+ x, y, w, h, leftPad, format, data);
+
+ 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;
+
+ int x, y;
+ int w, h;
+ int saveTrap;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateDrawableBitmap: Creating synchronization bitmap for [%s] at [%p].\n",
+ nxagentDrawableType(pDrawable), (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;
+ }
+
+ /*
+ * FIXME: A better way it would be create the bitmap
+ * with the same extents of the clipRegion. This
+ * requires to save the offset with respect to the
+ * drawable origin like in the backing store. This
+ * becomes particularly important when the drawable
+ * is a huge window, because the pixmap creation
+ * would fail.
+ */
+
+ pBitmap = nxagentCreatePixmap(pDrawable -> pScreen, pDrawable -> width, pDrawable -> height, pDrawable -> depth);
+
+ if (pBitmap == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCreateDrawableBitmap: Cannot create pixmap for the bitmap data.\n");
+ #endif
+
+ goto nxagentCreateDrawableBitmapEnd;
+ }
+
+ 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;
+
+ nxagentCopyArea(pDrawable, (DrawablePtr) pBitmap, pGC, x, y, w, h, x, y);
+
+ 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 (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);
+
+ /*
+ * Reduce the overall region to expose.
+ */
+
+ REGION_TRANSLATE(pWin -> pScreen, &expose, -pWin -> drawable.x, -pWin -> drawable.y);
+
+ REGION_SUBTRACT(pWin -> pScreen, pExpose, pExpose, &expose);
+
+ REGION_TRANSLATE(pWin -> pScreen, &expose, pWin -> drawable.x, pWin -> drawable.y);
+
+ 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..c987fa119
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Drawable.h
@@ -0,0 +1,221 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..43bf85900
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Error.c
@@ -0,0 +1,636 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#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..e55fd71a5
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Error.h
@@ -0,0 +1,37 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..ce84c1b19
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c
@@ -0,0 +1,4739 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 "dix.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 "Error.h"
+
+#include "NX.h"
+#include "NXvars.h"
+#include "NXproto.h"
+
+#include "xfixesproto.h"
+#define Window XlibWindow
+#define Atom XlibAtom
+#define Time XlibXID
+#include <X11/extensions/Xfixes.h>
+#undef Window
+#undef Atom
+#undef Time
+
+#ifdef NXAGENT_FIXKEYS
+#include "inputstr.h"
+#include "input.h"
+#endif
+
+#define Time XlibXID
+#include "XKBlib.h"
+#undef Time
+
+#define GC XlibGC
+#define Font XlibFont
+#define KeySym XlibKeySym
+#define XID XlibXID
+#include "Xlibint.h"
+#undef GC
+#undef Font
+#undef KeySym
+#undef XID
+
+#include <X11/cursorfont.h>
+
+#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 NX_DEBUG_INPUT
+int nxagentDebugInput = 0;
+#endif
+
+#ifdef DEBUG
+extern Bool nxagentRootlessTreesMatch(void);
+#endif
+
+extern Selection *CurrentSelections;
+extern int NumCurrentSelections;
+
+typedef union _XFixesSelectionEvent {
+ int type;
+ XFixesSelectionNotifyEvent xfixesselection;
+ XEvent core;
+} XFixesSelectionEvent;
+
+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;
+
+static int lastEventSerial = 0;
+
+#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);
+
+/*
+ * 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);
+
+/*
+ * 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()
+{
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessInputEvents: Processing input.\n");
+ }
+ #endif
+
+ mieqProcessInputEvents();
+}
+
+#ifdef DEBUG_TREE
+
+/*
+ * Print ID and name of window.
+ */
+
+void nxagentRemoteWindowID(Window window, Bool newline)
+{
+#ifdef NO_I18N
+ char *winName;
+#else
+ XTextProperty tp;
+#endif
+
+ fprintf(stderr, "0x%lx", window);
+
+ if (!window)
+ {
+ fprintf(stderr, " (none) ");
+ }
+ else
+ {
+ if (window == DefaultRootWindow(nxagentDisplay))
+ {
+ fprintf(stderr, " (the root window) ");
+ }
+
+#ifdef NO_I18N
+
+ if (!XFetchName(nxagentDisplay, window, &winName))
+ {
+ fprintf(stderr, " (has no name) ");
+ }
+ else if (winName)
+ {
+ fprintf(stderr, " \"%s\" ", winName);
+ XFree(winName);
+ }
+
+#else
+
+ if (XGetWMName(nxagentDisplay, window, &tp) != 0)
+ {
+ fprintf(stderr, " (has no name) ");
+ }
+ else if (tp.nitems > 0)
+ {
+ int count = 0;
+ int i, ret;
+ char **list = NULL;
+
+ fprintf(stderr, " \"");
+
+ ret = XmbTextPropertyToTextList(nxagentDisplay, &tp, &list, &count);
+
+ if ((ret == Success || ret > 0) && list != NULL)
+ {
+ for (i = 0; i < count; i++)
+ {
+ fprintf(stderr, "%s", list[i]);
+ }
+
+ XFreeStringList(list);
+ }
+ else
+ {
+ fprintf(stderr, "%s", tp.value);
+ }
+
+ fprintf(stderr, "\" ");
+ }
+
+#endif
+
+ else
+ {
+ fprintf(stderr, " (has no name) ");
+ }
+ }
+
+ if (newline == TRUE)
+ {
+ fprintf(stderr, "\n");
+ }
+
+ return;
+}
+
+/*
+ * Print info about remote window.
+ */
+
+void nxagentRemoteWindowInfo(Window win, int indent, Bool newLine)
+{
+ XWindowAttributes attributes;
+ int i;
+
+ if (XGetWindowAttributes(nxagentDisplay, win, &attributes) == 0)
+ {
+ return;
+ }
+
+ for (i = 0; i < indent; i++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ fprintf(stderr, "x=%d y=%d width=%d height=%d class=%s map_state=%s "
+ "override_redirect=%s\n", attributes.x, attributes.y,
+ attributes.width, attributes.height, (attributes.class == 0) ?
+ "InputOutput" : "InputOnly", (attributes.map_state == 0) ?
+ "IsUnmapped" : (attributes.map_state == 1 ?
+ "IsUnviewable" : "IsViewable"),
+ (attributes.override_redirect == 0) ?
+ "No" : "Yes" );
+
+ if (newLine == TRUE)
+ {
+ fprintf(stderr, "\n");
+ }
+}
+
+/*
+ * Walk remote windows tree.
+ */
+
+void nxagentRemoteWindowsTree(Window window, int level)
+{
+ int i, j;
+ Window rootWin, parentWin;
+ unsigned int numChildren;
+ Window *childList;
+
+ if (!XQueryTree(nxagentDisplay, window, &rootWin, &parentWin, &childList,
+ &numChildren))
+ {
+ fprintf(stderr, "nxagentRemoteWindowsTree - XQueryTree failed.\n");
+
+ return;
+ }
+
+ if (level == 0)
+ {
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Root Window ID: ");
+ nxagentRemoteWindowID(rootWin, TRUE);
+
+ fprintf(stderr, " Parent window ID: ");
+ nxagentRemoteWindowID(parentWin, TRUE);
+ }
+
+ if (level == 0 || numChildren > 0)
+ {
+ fprintf(stderr, " ");
+
+ for (j = 0; j < level; j++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ fprintf(stderr, "%d child%s%s\n", numChildren, (numChildren == 1) ? "" :
+ "ren", (numChildren == 1) ? ":" : ".");
+ }
+
+ for (i = (int) numChildren - 1; i >= 0; i--)
+ {
+ fprintf(stderr, " ");
+
+ for (j = 0; j < level; j++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ nxagentRemoteWindowID(childList[i], TRUE);
+
+ nxagentRemoteWindowInfo(childList[i], (level * 5) + 6, TRUE);
+
+ nxagentRemoteWindowsTree(childList[i], level + 1);
+ }
+
+ if (childList)
+ {
+ XFree((char *) childList);
+ }
+}
+
+/*
+ * Print info about internal window.
+ */
+
+void nxagentInternalWindowInfo(WindowPtr pWin, int indent, Bool newLine)
+{
+ int i;
+ int result;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ Atom atomReturnType;
+ int iReturnFormat;
+ unsigned char *pszReturnData = NULL;
+
+ fprintf(stderr, "Window ID=[0x%lx] Remote ID=[0x%lx] ", pWin -> drawable.id,
+ nxagentWindow(pWin));
+
+ result = GetWindowProperty(pWin, MakeAtom("WM_NAME", 7, False) , 0,
+ sizeof(CARD32), False, AnyPropertyType,
+ &atomReturnType, &iReturnFormat,
+ &ulReturnItems, &ulReturnBytesLeft,
+ &pszReturnData);
+
+ fprintf(stderr, "Name: ");
+
+ if (result == Success && pszReturnData != NULL)
+ {
+ pszReturnData[ulReturnItems] = '\0';
+
+ fprintf(stderr, "\"%s\"\n", (char *) pszReturnData);
+ }
+ else
+ {
+ fprintf(stderr, "%s\n", "( has no name )");
+ }
+
+ for (i = 0; i < indent; i++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ fprintf(stderr, "x=%d y=%d width=%d height=%d class=%s map_state=%s "
+ "override_redirect=%s", pWin -> drawable.x, pWin -> drawable.y,
+ pWin -> drawable.width, pWin -> drawable.height,
+ (pWin -> drawable.class == 0) ? "InputOutput" :
+ "InputOnly", (pWin -> mapped == 0) ?
+ "IsUnmapped" : (pWin -> mapped == 1 ?
+ "IsUnviewable" : "IsViewable"),
+ (pWin -> overrideRedirect == 0) ?
+ "No" : "Yes");
+
+ if (newLine == TRUE)
+ {
+ fprintf(stderr, "\n");
+ }
+}
+
+/*
+ * Walk internal windows tree.
+ */
+
+void nxagentInternalWindowsTree(WindowPtr pWin, int indent)
+{
+ WindowPtr pChild;
+ int i;
+
+ while (pWin)
+ {
+ pChild = pWin -> firstChild;
+
+ for (i = 0; i < indent; i++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ nxagentInternalWindowInfo(pWin, indent, TRUE);
+
+ fprintf(stderr, "\n");
+
+ nxagentInternalWindowsTree(pChild, indent + 4);
+
+ pWin = pWin -> nextSib;
+ }
+}
+
+#endif /* DEBUG_TREE */
+
+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);
+
+ if (nxagentOption(Fullscreen) == 0)
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ &sizeHints);
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Info: Enabled desktop resize mode in agent.\n");
+
+ nxagentLaunchDialog(DIALOG_ENABLE_DESKTOP_RESIZE_MODE);
+
+ nxagentChangeScreenConfig(0, nxagentOption(Width), nxagentOption(Height),
+ 0, 0);
+
+ if (nxagentOption(ClientOs) == ClientOsWinnt)
+ {
+ NXSetExposeParameters(nxagentDisplay, 0, 0, 0);
+ }
+
+ 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;
+ Bool switchAllScreens = 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;
+ }
+
+ #ifdef DEBUG_TREE
+
+ case doDebugTree:
+ {
+ fprintf(stderr, "\n ========== nxagentRemoteWindowsTree ==========\n");
+ nxagentRemoteWindowsTree(nxagentWindow(WindowTable[0]), 0);
+
+ fprintf(stderr, "\n========== nxagentInternalWindowsTree ==========\n");
+ nxagentInternalWindowsTree(WindowTable[0], 0);
+
+ break;
+ }
+
+ #endif /* DEBUG_TREE */
+
+ case doCloseSession:
+ {
+ closeSession = TRUE;
+
+ break;
+ }
+ case doMinimize:
+ {
+ minimize = TRUE;
+
+ break;
+ }
+ case doStartKbd:
+ {
+ startKbd = TRUE;
+
+ break;
+ }
+ case doSwitchFullscreen:
+ {
+ switchFullscreen = TRUE;
+
+ break;
+ }
+ case doSwitchAllScreens:
+ {
+ switchAllScreens = TRUE;
+
+ break;
+ }
+ case doViewportMoveUp:
+ {
+ nxagentMoveViewport(pScreen, 0, -nxagentOption(Height));
+
+ break;
+ }
+ case doViewportMoveDown:
+ {
+ nxagentMoveViewport(pScreen, 0, nxagentOption(Height));
+
+ break;
+ }
+ case doViewportMoveLeft:
+ {
+ nxagentMoveViewport(pScreen, -nxagentOption(Width), 0);
+
+ break;
+ }
+ case doViewportMoveRight:
+ {
+ nxagentMoveViewport(pScreen, nxagentOption(Width), 0);
+
+ 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)
+ {
+ X.xkey.keycode = nxagentConvertKeycode(X.xkey.keycode);
+
+ NXShadowEvent(nxagentDisplay, X);
+ }
+
+ break;
+ }
+ case KeyRelease:
+ {
+ enum HandleEventResult result;
+ int sendKey = 0;
+
+/*
+FIXME: If we don't flush the queue here, it could happen
+ that the inputInfo structure will not be up to date
+ when we perform the following check on down keys.
+*/
+ ProcessInputEvents();
+
+/*
+FIXME: Don't enqueue the KeyRelease event if the key was
+ not already pressed. This workaround avoids a fake
+ KeyPress is enqueued by the XKEYBOARD extension.
+ Another solution would be to let the events are
+ enqueued and to remove the KeyPress afterwards.
+*/
+ if (BitIsOn(inputInfo.keyboard -> key -> down,
+ nxagentConvertKeycode(X.xkey.keycode)))
+ {
+ sendKey = 1;
+ }
+
+ #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)
+ {
+ if (X.xkey.keycode == 66)
+ {
+ nxagentXkbCapsTrap = 1;
+ }
+ else if (X.xkey.keycode == 77)
+ {
+ nxagentXkbNumTrap = 1;
+ }
+
+ nxagentInitKeyboardState();
+
+ nxagentXkbCapsTrap = 0;
+ nxagentXkbNumTrap = 0;
+ }
+
+ x.u.u.type = KeyRelease;
+ x.u.u.detail = nxagentConvertKeycode(X.xkey.keycode);
+ x.u.keyButtonPointer.time = nxagentLastKeyPressTime +
+ (X.xkey.time - nxagentLastServerTime);
+
+ nxagentLastServerTime = X.xkey.time;
+
+ nxagentLastEventTime = GetTimeInMillis();
+
+ if (x.u.keyButtonPointer.time > nxagentLastEventTime)
+ {
+ x.u.keyButtonPointer.time = nxagentLastEventTime;
+ }
+
+ if (!(nxagentCheckSpecialKeystroke(&X.xkey, &result)) && sendKey == 1)
+ {
+ mieqEnqueue(&x);
+
+ CriticalOutputPending = 1;
+
+ if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow))
+ {
+ X.xkey.keycode = nxagentConvertKeycode(X.xkey.keycode);
+
+ NXShadowEvent(nxagentDisplay, X);
+ }
+ }
+
+ break;
+ }
+ case ButtonPress:
+ {
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ 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 = inputInfo.pointer -> button -> map[nxagentReversePointerMap[X.xbutton.button - 1]];
+ 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);
+ }
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Adding ButtonPress event.\n");
+ }
+ #endif
+
+ 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 NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ 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 = inputInfo.pointer -> button -> map[nxagentReversePointerMap[X.xbutton.button - 1]];
+ 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);
+ }
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Adding ButtonRelease event.\n");
+ }
+ #endif
+
+ 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 NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ 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 && nxagentLastEnteredTopLevelWindow &&
+ (X.xmotion.y_root < nxagentLastEnteredTopLevelWindow -> drawable.y + 4))
+ {
+ if (pWin && 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))
+ {
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Adding motion event [%d, %d] to the queue.\n",
+ x.u.keyButtonPointer.rootX, x.u.keyButtonPointer.rootY);
+ }
+ #endif
+
+ 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) == 1 &&
+ 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 (X.xcrossing.window == nxagentDefaultWindows[0] &&
+ X.xcrossing.detail != NotifyInferior &&
+ X.xcrossing.mode == NotifyNormal)
+ {
+ nxagentUngrabPointerAndKeyboard(&X);
+ }
+
+ 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
+ if (nxagentVerbose == 1)
+ {
+ 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(AllScreens) == 1)
+ {
+ if (X.xmap.window == nxagentIconWindow)
+ {
+ pScreen = nxagentScreen(X.xmap.window);
+ nxagentMaximizeToFullScreen(pScreen);
+ }
+ }
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ nxagentVisibility = VisibilityUnobscured;
+ nxagentVisibilityStop = False;
+ nxagentVisibilityTimeout = GetTimeInMillis() + 2000;
+ }
+
+ break;
+ }
+ case MappingNotify:
+ {
+ XMappingEvent *mappingEvent = (XMappingEvent *) &X;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! Going to handle new MappingNotify event.\n");
+ #endif
+
+ if (mappingEvent -> request == MappingPointer)
+ {
+ nxagentInitPointerMap();
+ }
+
+ break;
+ }
+ default:
+ {
+ /*
+ * Let's check if this is a XKB
+ * state modification event.
+ */
+
+ if (nxagentHandleKeyboardEvent(&X) == 0 && nxagentHandleXFixesSelectionNotify(&X) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! Unhandled event code [%d].\n",
+ X.type);
+ #endif
+ }
+
+ break;
+ }
+
+ } /* End of switch (X.type) */
+
+ if (X.xany.serial < lastEventSerial)
+ {
+ /*
+ * Start over.
+ */
+
+ nxagentDeleteStaticResizedWindow(0);
+ }
+ else
+ {
+ nxagentDeleteStaticResizedWindow(X.xany.serial - 1);
+ }
+
+ lastEventSerial = X.xany.serial;
+
+ } /* 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(AllScreens))
+ {
+ nxagentMinimizeFromFullScreen(pScreen);
+ }
+ else
+ {
+ XIconifyWindow(nxagentDisplay, nxagentDefaultWindows[0],
+ DefaultScreen(nxagentDisplay));
+ }
+ }
+ }
+
+ if (switchFullscreen)
+ {
+ if (nxagentOption(AllScreens) == 1 && nxagentOption(Fullscreen) == 1)
+ {
+ nxagentSwitchAllScreens(pScreen, 0);
+ }
+ else
+ {
+ nxagentSwitchFullscreen(pScreen, !nxagentOption(Fullscreen));
+ }
+ }
+
+ if (switchAllScreens)
+ {
+ if (nxagentOption(AllScreens) == 0 && nxagentOption(Fullscreen) == 1)
+ {
+ nxagentSwitchFullscreen(pScreen, 0);
+ }
+ else
+ {
+ nxagentSwitchAllScreens(pScreen, !nxagentOption(AllScreens));
+ }
+ }
+
+ 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)
+ {
+ if (X -> xkey.keycode == 66)
+ {
+ nxagentXkbCapsTrap = 1;
+ }
+ else if (X -> xkey.keycode == 77)
+ {
+ nxagentXkbNumTrap = 1;
+ }
+
+ nxagentInitKeyboardState();
+
+ nxagentXkbCapsTrap = 0;
+ nxagentXkbNumTrap = 0;
+ }
+
+ if (nxagentCheckSpecialKeystroke(&X -> xkey, result))
+ {
+ return 1;
+ }
+
+ if (X -> xkey.keycode == 66)
+ {
+ nxagentXkbState.Caps = (~nxagentXkbState.Caps & 1);
+ }
+ else if (X -> xkey.keycode == 77)
+ {
+ nxagentXkbState.Num = (~nxagentXkbState.Num & 1);
+ }
+
+ nxagentLastEventTime = nxagentLastKeyPressTime = GetTimeInMillis();
+
+ x.u.u.type = KeyPress;
+ x.u.u.detail = nxagentConvertKeycode(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;
+
+ StaticResizedWindowStruct *resizedWinPtr = NULL;
+
+ #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;
+
+ resizedWinPtr = nxagentFindStaticResizedWindow(X -> xany.serial);
+
+ while (resizedWinPtr)
+ {
+ if (resizedWinPtr -> pWin == pWin)
+ {
+ box.x1 += resizedWinPtr -> offX;
+ box.y1 += resizedWinPtr -> offY;
+ }
+
+ resizedWinPtr = resizedWinPtr -> prev;
+ }
+
+ 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);
+
+ XMapRaised(nxagentDisplay, nxagentFullscreenWindow);
+
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+
+ }
+
+ if (X -> xclient.window == (nxagentOption(Fullscreen) ?
+ nxagentIconWindow : nxagentDefaultWindows[0]) ||
+ nxagentWMIsRunning == 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
+
+ if (!nxagentXkbCapsTrap)
+ {
+ 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.Caps == 0 &&
+ !(nxagentXkbState.Locked & CAPSFLAG_IN_EVENT) &&
+ nxagentXkbCapsTrap)
+ {
+
+ #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
+
+ if (!nxagentXkbNumTrap)
+ {
+ 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);
+ }
+
+ if (nxagentXkbState.Num == 0 &&
+ !(nxagentXkbState.Locked & NUMFLAG_IN_EVENT) &&
+ nxagentXkbNumTrap)
+ {
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [77] to release numlock.\n");
+ #endif
+
+ nxagentSendFakeKey(77);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int nxagentHandleXFixesSelectionNotify(XEvent *X)
+{
+ int i;
+ Atom local;
+
+ XFixesSelectionEvent *xfixesEvent = (XFixesSelectionEvent *) X;
+
+ if (nxagentXFixesInfo.Initialized == 0 ||
+ xfixesEvent -> type != (nxagentXFixesInfo.EventBase + XFixesSelectionNotify))
+ return 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Handling event.\n");
+ #endif
+
+ local = nxagentRemoteToLocalAtom(xfixesEvent -> xfixesselection.selection);
+
+ if (SelectionCallback)
+ {
+ i = 0;
+
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != local)
+ i++;
+
+ if (i < NumCurrentSelections)
+ {
+ SelectionInfoRec info;
+
+ if (CurrentSelections[i].client != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Do nothing.\n");
+ #endif
+
+ return 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Calling callbacks for %d [%s] selection.\n",
+ CurrentSelections[i].selection, NameForAtom(CurrentSelections[i].selection));
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Subtype ");
+
+ switch (xfixesEvent -> xfixesselection.subtype)
+ {
+ case SelectionSetOwner:
+ fprintf(stderr, "SelectionSetOwner.\n");
+ break;
+ case SelectionWindowDestroy:
+ fprintf(stderr, "SelectionWindowDestroy.\n");
+ break;
+ case SelectionClientClose:
+ fprintf(stderr, "SelectionClientClose.\n");
+ break;
+ default:
+ fprintf(stderr, ".\n");
+ break;
+ }
+ #endif
+
+ info.selection = &CurrentSelections[i];
+ info.kind = xfixesEvent->xfixesselection.subtype;
+ CallCallbacks(&SelectionCallback, &info);
+ }
+ }
+ return 1;
+}
+
+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(AllScreens) == 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;
+ }
+
+ nxagentChangeOption(Width, X -> xconfigure.width);
+ nxagentChangeOption(Height, X -> xconfigure.height);
+
+ XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0,
+ X -> xconfigure.width, X -> xconfigure.height);
+
+ if (nxagentOption(Fullscreen) == 0)
+ {
+ nxagentMoveViewport(pScreen, 0, 0);
+ }
+ else
+ {
+ 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));
+
+ nxagentUpdateViewportFrame(0, 0, nxagentOption(RootWidth),
+ nxagentOption(RootHeight));
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(WindowTable[pScreen -> myNum]),
+ nxagentOption(RootX), nxagentOption(RootY));
+ }
+
+ if (doRandR)
+ {
+ #ifdef TEST
+ fprintf(stderr,"nxagentHandleConfigureNotify: Width %d Height %d.\n",
+ nxagentOption(Width), nxagentOption(Height));
+ #endif
+
+ nxagentChangeScreenConfig(0, nxagentOption(Width),
+ nxagentOption(Height), 0, 0);
+ }
+ }
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int nxagentHandleReparentNotify(XEvent* X)
+{
+ #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
+
+ break;
+ }
+
+ 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 if (nxagentWMIsRunning == 1 && nxagentOption(Fullscreen) == 0 &&
+ nxagentOption(WMBorderWidth) == -1)
+ {
+ XlibWindow w;
+ XlibWindow rootReturn = 0;
+ XlibWindow parentReturn = 0;
+ XlibWindow junk;
+ XlibWindow *childrenReturn = NULL;
+ unsigned int nchildrenReturn = 0;
+ Status result;
+ XWindowAttributes attributes;
+ int x, y;
+ int xParent, yParent;
+
+ /*
+ * Calculate the absolute upper-left X e Y
+ */
+
+ if ((XGetWindowAttributes(nxagentDisplay, X -> xreparent.window,
+ &attributes) == 0))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleReparentNotify: WARNING! "
+ "XGetWindowAttributes failed.\n");
+ #endif
+
+ return 1;
+ }
+
+ x = attributes.x;
+ y = attributes.y;
+
+ XTranslateCoordinates(nxagentDisplay, X -> xreparent.window,
+ attributes.root, -attributes.border_width,
+ -attributes.border_width, &x, &y, &junk);
+
+ /*
+ * Calculate the parent X and parent Y.
+ */
+
+ w = X -> xreparent.parent;
+
+ if (w != DefaultRootWindow(nxagentDisplay))
+ {
+ do
+ {
+ result = XQueryTree(nxagentDisplay, w, &rootReturn, &parentReturn,
+ &childrenReturn, &nchildrenReturn);
+
+ if (parentReturn == rootReturn || parentReturn == 0 || result == 0)
+ {
+ break;
+ }
+
+ if (result == 1 && childrenReturn != NULL)
+ {
+ XFree(childrenReturn);
+ }
+
+ w = parentReturn;
+ }
+ while (True);
+
+ /*
+ * WM reparented. Find edge of the frame.
+ */
+
+ if (XGetWindowAttributes(nxagentDisplay, w, &attributes) == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleReparentNotify: WARNING! "
+ "XGetWindowAttributes failed for parent window.\n");
+ #endif
+
+ return 1;
+ }
+
+ xParent = attributes.x;
+ yParent = attributes.y;
+
+ /*
+ * Difference between Absolute X and Parent X gives thickness of side frame.
+ * Difference between Absolute Y and Parent Y gives thickness of title bar.
+ */
+
+ nxagentChangeOption(WMBorderWidth, (x - xParent));
+ nxagentChangeOption(WMTitleHeight, (y - yParent));
+ }
+ }
+
+ 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;
+
+ int result;
+
+ #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
+
+ result = XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow,
+ True, GrabModeAsync, GrabModeAsync, now);
+
+ if (result != GrabSuccess)
+ {
+ return;
+ }
+
+ /*
+ * The smart scheduler could be stopped while
+ * waiting for the reply. In this case we need
+ * to yield explicitly to avoid to be stuck in
+ * the dispatch loop forever.
+ */
+
+ isItTimeToYield = 1;
+
+ #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 &&
+ ((pWin -> eventMask|wOtherEventMasks(pWin)) & ExposureMask))
+ {
+ #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;
+}
+
+#ifdef NX_DEBUG_INPUT
+
+void nxagentDumpInputInfo(void)
+{
+ fprintf(stderr, "Dumping input info ON.\n");
+}
+
+void nxagentGuessDumpInputInfo(ClientPtr client, Atom property, char *data)
+{
+ if (strcmp(validateString(NameForAtom(property)), "NX_DEBUG_INPUT") == 0)
+ {
+ if (*data != 0)
+ {
+ nxagentDebugInput = 1;
+ }
+ else
+ {
+ nxagentDebugInput = 0;
+ }
+ }
+}
+
+void nxagentDeactivateInputDevicesGrabs()
+{
+ fprintf(stderr, "Info: Deactivating input devices grabs.\n");
+
+ if (inputInfo.pointer -> grab)
+ {
+ (*inputInfo.pointer -> DeactivateGrab)(inputInfo.pointer);
+ }
+
+ if (inputInfo.keyboard -> grab)
+ {
+ (*inputInfo.keyboard -> DeactivateGrab)(inputInfo.keyboard);
+ }
+}
+
+static const char *nxagentGrabStateToString(int state)
+{
+ switch (state)
+ {
+ case 0:
+ return "NOT_GRABBED";
+ case 1:
+ return "THAWED";
+ case 2:
+ return "THAWED_BOTH";
+ case 3:
+ return "FREEZE_NEXT_EVENT";
+ case 4:
+ return "FREEZE_BOTH_NEXT_EVENT";
+ case 5:
+ return "FROZEN_NO_EVENT";
+ case 6:
+ return "FROZEN_WITH_EVENT";
+ case 7:
+ return "THAW_OTHERS";
+ default:
+ return "unknown state";
+ }
+}
+
+void nxagentDumpInputDevicesState(void)
+{
+ int i, k;
+ int mask = 1;
+ CARD8 val;
+ DeviceIntPtr dev;
+ GrabPtr grab;
+ WindowPtr pWin = NULL;
+
+ fprintf(stderr, "\n*** Dump input devices state: BEGIN ***"
+ "\nKeys down:");
+
+ dev = inputInfo.keyboard;
+
+ for (i = 0; i < DOWN_LENGTH; i++)
+ {
+ val = dev -> key -> down[i];
+
+ if (val != 0)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ if (val & (mask << k))
+ {
+ fprintf(stderr, "\n\t[%d] [%s]", i * 8 + k,
+ XKeysymToString(XKeycodeToKeysym(nxagentDisplay, i * 8 + k, 0)));
+ }
+ }
+ }
+ }
+
+ fprintf(stderr, "\nKeyboard device state: \n\tdevice [%p]\n\tlast grab time [%lu]"
+ "\n\tfrozen [%s]\n\tstate [%s]\n\tother [%p]\n\tevent count [%d]"
+ "\n\tfrom passive grab [%s]\n\tactivating key [%d]", dev,
+ dev -> grabTime.milliseconds, dev -> sync.frozen ? "Yes": "No",
+ nxagentGrabStateToString(dev -> sync.state),
+ dev -> sync.other, dev -> sync.evcount,
+ dev -> fromPassiveGrab ? "Yes" : "No",
+ dev -> activatingKey);
+
+ grab = dev -> grab;
+
+ if (grab)
+ {
+ fprintf(stderr, "\nKeyboard grab state: \n\twindow pointer [%p]"
+ "\n\towner events flag [%s]\n\tgrab mode [%s]",
+ grab -> window, grab -> ownerEvents ? "True" : "False",
+ grab -> keyboardMode ? "asynchronous" : "synchronous");
+
+ /*
+ * Passive grabs.
+ */
+
+ pWin = grab -> window;
+ grab = wPassiveGrabs(pWin);
+
+ while (grab)
+ {
+ fprintf(stderr, "\nPassive grab state: \n\tdevice [%p]\n\towner events flag [%s]"
+ "\n\tpointer grab mode [%s]\n\tkeyboard grab mode [%s]\n\tevent type [%d]"
+ "\n\tmodifiers [%x]\n\tbutton/key [%u]\n\tevent mask [%lx]",
+ grab -> device, grab -> ownerEvents ? "True" : "False",
+ grab -> pointerMode ? "asynchronous" : "synchronous",
+ grab -> keyboardMode ? "asynchronous" : "synchronous",
+ grab -> type, grab -> modifiersDetail.exact,
+ grab -> detail.exact, grab -> eventMask);
+
+ grab = grab -> next;
+ }
+ }
+
+ fprintf(stderr, "\nButtons down:");
+
+ dev = inputInfo.pointer;
+
+ for (i = 0; i < DOWN_LENGTH; i++)
+ {
+ val = dev -> button -> down[i];
+
+ if (val != 0)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ if (val & (mask << k))
+ {
+ fprintf(stderr, "\n\t[%d]", i * 8 + k);
+ }
+ }
+ }
+ }
+
+ fprintf(stderr, "\nPointer device state: \n\tdevice [%p]\n\tlast grab time [%lu]"
+ "\n\tfrozen [%s]\n\tstate [%s]\n\tother [%p]\n\tevent count [%d]"
+ "\n\tfrom passive grab [%s]\n\tactivating button [%d]", dev,
+ dev -> grabTime.milliseconds, dev -> sync.frozen ? "Yes" : "No",
+ nxagentGrabStateToString(dev -> sync.state),
+ dev -> sync.other, dev -> sync.evcount,
+ dev -> fromPassiveGrab ? "Yes" : "No",
+ dev -> activatingKey);
+
+ grab = dev -> grab;
+
+ if (grab)
+ {
+ fprintf(stderr, "\nPointer grab state: \n\twindow pointer [%p]"
+ "\n\towner events flag [%s]\n\tgrab mode [%s]",
+ grab -> window, grab -> ownerEvents ? "True" : "False",
+ grab -> pointerMode ? "asynchronous" : "synchronous");
+
+ if (grab -> window != pWin)
+ {
+ /*
+ * Passive grabs.
+ */
+
+ grab = wPassiveGrabs(grab -> window);
+
+ while (grab)
+ {
+ fprintf(stderr, "\nPassive grab state: \n\tdevice [%p]\n\towner events flag [%s]"
+ "\n\tpointer grab mode [%s]\n\tkeyboard grab mode [%s]\n\tevent type [%d]"
+ "\n\tmodifiers [%x]\n\tbutton/key [%u]\n\tevent mask [%lx]",
+ grab -> device, grab -> ownerEvents ? "True" : "False",
+ grab -> pointerMode ? "asynchronous" : "synchronous",
+ grab -> keyboardMode ? "asynchronous" : "synchronous",
+ grab -> type, grab -> modifiersDetail.exact,
+ grab -> detail.exact, grab -> eventMask);
+
+ grab = grab -> next;
+ }
+ }
+ }
+
+ fprintf(stderr, "\n*** Dump input devices state: FINISH ***\n");
+}
+
+#endif
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..c74fa151f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Events.h
@@ -0,0 +1,230 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifndef __Events_H__
+#define __Events_H__
+
+#include <X11/Xmd.h>
+
+#define ProcessedExpose (LASTEvent + 1)
+#define ProcessedNotify (LASTEvent + 2)
+
+#define EXPOSED_SIZE 256
+
+enum HandleEventResult
+{
+ doNothing = 0,
+ doMinimize,
+ doDebugTree,
+ doCloseSession,
+ doStartKbd,
+ doSwitchFullscreen,
+ doSwitchAllScreens,
+ doViewportMoveUp,
+ doViewportMoveLeft,
+ doViewportMoveRight,
+ doViewportMoveDown,
+ 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);
+extern int nxagentHandleXFixesSelectionNotify(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..6dce644ae
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Extensions.c
@@ -0,0 +1,321 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include "micmap.h"
+#include "scrnintstr.h"
+#include "../../randr/randrstr.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Options.h"
+#include "Extensions.h"
+#include "Windows.h"
+
+void GlxExtensionInit(void);
+void GlxWrapInitVisuals(void *procPtr);
+
+static int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width,
+ CARD16 height, CARD32 mmWidth,
+ CARD32 mmHeight);
+
+static int nxagentRandRInitSizes(ScreenPtr pScreen);
+
+#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");
+ }
+
+ nxagentRandRInitSizes(pScreen);
+
+ /*
+ * RRScreenInit sets these pointers to NULL,
+ * so requiring the server to set up its own
+ * replacements.
+ */
+
+ pRandRScrPriv = rrGetScrPriv(pScreen);
+
+ pRandRScrPriv -> rrGetInfo = nxagentRandRGetInfo;
+
+ #if RANDR_12_INTERFACE
+ pRandRScrPriv -> rrScreenSetSize = nxagentRandRScreenSetSize;
+ #endif
+
+ #if RANDR_10_INTERFACE
+ pRandRScrPriv -> rrSetConfig = nxagentRandRSetConfig;
+ #endif
+}
+
+int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
+{
+ /*
+ * Rotation is not supported.
+ */
+
+ *pRotations = RR_Rotate_0;
+
+ return 1;
+}
+
+static int nxagentRandRInitSizes(ScreenPtr pScreen)
+{
+ RRScreenSizePtr pSize;
+ rrScrPrivPtr pRandRScrPriv = rrGetScrPriv(pScreen);
+
+ int width;
+ int height;
+
+ int maxWidth;
+ int maxHeight;
+
+/*
+ int w[] = {0, 160, 320, 640, 800, 1024, 1152, 1280, 1280, 1280, 1280, 1280,
+ 1280, 1360, 1440, 1600, 1600, 1680, 1920, 1920, 0, 0};
+ int h[] = {0, 120, 240, 480, 600, 768, 864, 600, 720, 800, 854, 960,
+ 1024, 768, 900, 900, 1200, 1050, 1080, 1200, 0, 0};
+*/
+ int w[] = {0, 320, 640, 640, 800, 800, 1024, 1024, 1152, 1280, 1280, 1280, 1360,
+ 1440, 1600, 1600, 1680, 1920, 1920, 0, 0};
+ int h[] = {0, 240, 360, 480, 480, 600, 600, 768, 864, 720, 800, 1024, 768,
+ 900, 900, 1200, 1050, 1080, 1200, 0, 0};
+
+ int i;
+ int nSizes;
+
+ int mmWidth;
+ int mmHeight;
+
+ /*
+ * 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;
+}
+
+#if RANDR_10_INTERFACE
+
+int nxagentRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
+ int rate, RRScreenSizePtr pSize)
+{
+ int r;
+ rrScrPrivPtr pRandRScrPriv;
+
+ UpdateCurrentTime();
+
+ /*
+ * Whatever size is OK for us.
+ */
+
+ r = nxagentResizeScreen(pScreen, pSize -> width, pSize -> height,
+ pSize -> mmWidth, pSize -> mmHeight);
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ return r;
+}
+
+#endif
+
+#if RANDR_12_INTERFACE
+
+void nxagentRandRSetWindowsSize(int width, int height)
+{
+ if (width == 0)
+ {
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ width = nxagentOption(Width);
+ }
+ }
+
+ if (height == 0)
+ {
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ height = nxagentOption(Height);
+ }
+ }
+
+ XResizeWindow(nxagentDisplay, nxagentDefaultWindows[0], width, height);
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0, width,
+ height);
+ }
+}
+
+int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
+{
+ int result;
+ rrScrPrivPtr pRandRScrPriv;
+
+ UpdateCurrentTime();
+
+ if (nxagentOption(DesktopResize) == 1 &&
+ (nxagentOption(Fullscreen) == 1 ||
+ width > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) ||
+ height > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))))
+ {
+ if (nxagentOption(ClientOs) != ClientOsWinnt
+ /*&& nxagentOption(ClientOs) != ClientNXPlayer*/)
+ {
+ nxagentChangeOption(DesktopResize, 0);
+ }
+ }
+
+ if (nxagentOption(DesktopResize) == 1 && nxagentOption(Fullscreen) == 0 &&
+ nxagentOption(AllScreens) == 0)
+ {
+ nxagentChangeOption(Width, width);
+ nxagentChangeOption(Height, height);
+ }
+
+ result = nxagentResizeScreen(pScreen, width, height, mmWidth, mmHeight);
+
+ if (result == 1 && nxagentOption(DesktopResize) == 1 &&
+ nxagentOption(Fullscreen) == 0 && nxagentOption(AllScreens) == 0)
+ {
+ nxagentRandRSetWindowsSize(width, height);
+ nxagentSetWMNormalHints(pScreen -> myNum);
+ }
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ return result;
+}
+
+#endif
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..5335cf87c
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Extensions.h
@@ -0,0 +1,35 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..178ed3cf7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Font.c
@@ -0,0 +1,1876 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <stdio.h>
+#include <sys/stat.h>
+#include "resource.h"
+#include "Reconnect.h"
+
+#include "Args.h"
+
+#include "NXlib.h"
+#include "NXalert.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#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_ALTERNATE_FONT_DIR_4 "/usr/NX/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/,\
+/usr/NX/share/fonts/base"
+
+#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/,\
+/usr/NX/share/fonts/base"
+
+#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/,\
+/usr/NX/share/fonts/base"
+
+#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/,\
+/usr/NX/share/fonts/base"
+
+#define NXAGENT_ALTERNATE_FONT_PATH_4 \
+"/usr/NX/share/fonts/base"
+
+#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);
+
+static char * nxagentMakeScalableFontName(const char *fontName, int scalableResolution);
+
+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;
+ int result;
+
+ char *scalable;
+
+ if (name != NULL && strlen(name) == 0)
+ {
+ return 0;
+ }
+
+ result = nxagentFontFind(name, &i);
+
+ scalable = NULL;
+
+ /*
+ * Let's try with the scalable font description.
+ */
+
+ if (result == 0)
+ {
+ scalable = nxagentMakeScalableFontName(name, 0);
+
+ if (scalable != NULL)
+ {
+ result = nxagentFontFind(scalable, &i);
+
+ free(scalable);
+ }
+ }
+
+ /*
+ * Let's try again after replacing zero to xdpi and ydpi in the pattern.
+ */
+
+ if (result == 0)
+ {
+ scalable = nxagentMakeScalableFontName(name, 1);
+
+ if (scalable != NULL)
+ {
+ result = nxagentFontFind(scalable, &i);
+
+ free(scalable);
+ }
+ }
+
+ if (result == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (nxagentRemoteFontList.list[i]->status > 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 + 1, "-");
+
+ 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
+ }
+
+ for (j = 0; j < numSearchFields; j++)
+ {
+ if (searchFields[j] != NULL)
+ {
+ free(searchFields[j]);
+ }
+ }
+ }
+ }
+
+ #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);
+
+ for (j = 0; j < numFontFields; j++)
+ {
+ if (fontNameFields[j] != NULL)
+ {
+ free(fontNameFields[j]);
+ }
+ }
+
+ 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 (stat(NXAGENT_ALTERNATE_FONT_DIR_4, &dirStat) == 0 &&
+ S_ISDIR(dirStat.st_mode) != 0)
+ {
+ /*
+ * Let's use the "/usr/NX/share/fonts" path.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n",
+ validateString(NXAGENT_ALTERNATE_FONT_DIR_4));
+ #endif
+
+ if (*fontPath != '\0')
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_4) + 2);
+ strcat(fontPath, ",");
+ }
+ else
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_4) + 1);
+ }
+
+ strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH_4);
+ }
+
+ 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;
+ }
+ else
+ {
+ fields[i] = NULL;
+ }
+
+ current = next + seplen;
+
+ i++;
+
+ if (last == 1)
+ {
+ break;
+ }
+ }
+
+ return i;
+}
+
+char *nxagentMakeScalableFontName(const char *fontName, int scalableResolution)
+{
+ char *scalableFontName;
+ const char *s;
+ int len;
+ int field;
+
+ len = strlen(fontName) + 1;
+
+ scalableFontName = malloc(len);
+
+ if (scalableFontName == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentMakeScalableFontName: PANIC! malloc() failed.\n");
+ #endif
+
+ return NULL;
+ }
+
+ scalableFontName[0] = 0;
+
+ if (*fontName != '-')
+ {
+ goto MakeScalableFontNameError;
+ }
+
+ s = fontName;
+
+ field = 0;
+
+ while (s != NULL)
+ {
+ s = strchr(s + 1, '-');
+
+ if (s != NULL)
+ {
+ if (field == 6 || field == 7 || field == 11)
+ {
+ /*
+ * PIXEL_SIZE || POINT_SIZE || AVERAGE_WIDTH
+ */
+
+ strcat(scalableFontName, "-0");
+ }
+ else if (scalableResolution == 1 && (field == 8 || field == 9))
+ {
+ /*
+ * RESOLUTION_X || RESOLUTION_Y
+ */
+
+ strcat(scalableFontName, "-0");
+ }
+ else
+ {
+ strncat(scalableFontName, fontName, s - fontName);
+ }
+
+ fontName = s;
+ }
+ else
+ {
+ strcat(scalableFontName, fontName);
+ }
+
+ field++;
+ }
+
+ if (field != 14)
+ {
+ goto MakeScalableFontNameError;
+ }
+
+ return scalableFontName;
+
+MakeScalableFontNameError:
+
+ free(scalableFontName);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentMakeScalableFontName: Invalid font name.\n");
+ #endif
+
+ return NULL;
+}
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..63cb6aa24
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Font.h
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..71562d999
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GC.c
@@ -0,0 +1,1712 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..e18b034eb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GCOps.c
@@ -0,0 +1,2100 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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];
+
+ Bool pClipRegionFree = True;
+
+ /*
+ * 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);
+
+ /*
+ * Next call to nxagentChangeClip() will destroy
+ * pClipRegion, so it has not to be freed.
+ */
+
+ pClipRegionFree = False;
+
+ #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);
+
+ if (pClipRegionFree == True)
+ {
+ nxagentFreeRegion(pSrcDrawable, pClipRegion);
+ }
+
+ 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;
+
+ int oldDstxyValue;
+
+ 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
+
+ /*
+ * Here, before using fbDoCopy() called by fbCopyArea(),
+ * it should be provided that the cast in fbDoCopy() from
+ * int to short int would not cut off significative bits.
+ */
+
+ if (dstx + pDstDrawable->x + width > 32767)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: x2 exceeding short int.\n");
+ #endif
+
+ width = 32767 - dstx - pDstDrawable->x;
+
+ if (width <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on x2 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+ if (dstx + pDstDrawable->x < -32768)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: x1 exceeding short int.\n");
+ #endif
+
+ width += pDstDrawable->x + dstx + 32768;
+ srcx -= pDstDrawable->x + dstx + 32768;
+ dstx = -32768 - pDstDrawable->x;
+
+ if (width <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on x1 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+ oldDstxyValue = dsty;
+
+ if (dsty + pDstDrawable->y + height > 32767)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: y2 exceeding short int.\n");
+ #endif
+
+ height = 32767 - dsty - pDstDrawable->y;
+
+ if (height <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on y2 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+ if (dsty + pDstDrawable->y < -32768)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: y1 exceeding short int.\n");
+ #endif
+
+ height += 32768 + pDstDrawable->y + dsty;
+ srcy -= 32768 + pDstDrawable->y + dsty;
+ dsty = -32768 - pDstDrawable->y;
+
+ if (height <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on y1 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+
+ 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);
+ }
+
+ SET_GC_TRAP();
+ fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments);
+ RESET_GC_TRAP();
+
+ return;
+ }
+ else
+ {
+ XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XSegment *) pSegments, nSegments);
+
+ SET_GC_TRAP();
+ fbPolySegment(pDrawable, pGC, nSegments, pSegments);
+ RESET_GC_TRAP();
+ }
+}
+
+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..fa4967aee
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GCOps.h
@@ -0,0 +1,105 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..f7e13477a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GCs.h
@@ -0,0 +1,111 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..310b572cc
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Handlers.c
@@ -0,0 +1,1311 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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"
+#include "Shadow.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
+
+#ifdef NX_DEBUG_INPUT
+extern int nxagentDebugInputDevices;
+extern unsigned long nxagentLastInputDevicesDumpTime;
+
+extern void nxagentDumpInputDevicesState(void);
+#endif
+
+/*
+ * 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();
+
+ #ifdef NX_DEBUG_INPUT
+
+ if (nxagentDebugInputDevices == 1 &&
+ now - nxagentLastInputDevicesDumpTime > 5000)
+ {
+ nxagentLastInputDevicesDumpTime = now;
+
+ nxagentDumpInputDevicesState();
+ }
+
+ #endif
+
+ 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 (NXDisplayError(nxagentDisplay) == 0 &&
+ 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
+
+ nxagentPrintGeometry();
+
+ #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;
+ int width_, height_;
+
+ #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;
+
+ NXShadowGetScreenSize(&width_, &height_);
+
+ if (width_ != nxagentShadowWidth || height_ != nxagentShadowHeight)
+ {
+ /*
+ * The master session has been resized.
+ */
+
+ NXShadowSetScreenSize(&nxagentShadowWidth, &nxagentShadowHeight);
+
+ nxagentShadowAdaptToRatio();
+ }
+
+ 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
+
+ nxagentPrintGeometry();
+
+ #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..3d3b335c0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Handlers.h
@@ -0,0 +1,121 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..bfd907cde
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Holder.c
@@ -0,0 +1,226 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <signal.h>
+#include <stdio.h>
+
+#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..c39b98780
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Holder.h
@@ -0,0 +1,27 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..0601584d4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Icons.h
@@ -0,0 +1,29 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifndef __Icons_H__
+#define __Icons_H__
+
+#define Pixel XpmPixel
+#include <X11/xpm.h>
+#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..e499b7a11
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Image.c
@@ -0,0 +1,1821 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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;
+
+ /*
+ * NXPutPackedImage is longer than PutPackedImage
+ * so that we subtract the bigger one to be sure.
+ */
+
+ const int subSize = (MAX_REQUEST_SIZE << 2) - sizeof(xNXPutPackedImageReq);
+
+ 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 && format == ZPixmap);
+
+ 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..57272ab18
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Image.h
@@ -0,0 +1,108 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..96579583b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Imakefile
@@ -0,0 +1,222 @@
+# XCOMM $Xorg: Imakefile,v 1.3 2000/08/17 19:53:28 cpqbld Exp $
+
+#include <Server.tmpl>
+
+#ifdef OS2Architecture
+SRCS1 = os2Stub.c
+OBJS1 = os2Stub.o
+#endif
+
+SRCS = 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 = 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 \
+ -UNX_DEBUG_INPUT \
+ -DRANDR_10_INTERFACE \
+ -DRANDR_12_INTERFACE \
+ -UPANORAMIX \
+ -UDEBUG_TREE
+
+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..f4fc3c7e5
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Init.c
@@ -0,0 +1,518 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <sys/types.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#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.5.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.
+ */
+
+
+static void nxagentGrabServerCallback(CallbackListPtr *callbacks, pointer data,
+ pointer args);
+
+#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, 2011 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 (serverGeneration == 1)
+ {
+ AddCallback(&ServerGrabCallback, nxagentGrabServerCallback, NULL);
+ }
+
+ 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;
+
+ /*
+ * Use a solid black root window
+ * background.
+ */
+
+ blackRoot = TRUE;
+}
+
+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
+
+ServerGrabInfoRec nxagentGrabServerInfo;
+
+static void nxagentGrabServerCallback(CallbackListPtr *callbacks, pointer data,
+ pointer args)
+{
+ ServerGrabInfoRec *grab = (ServerGrabInfoRec*)args;
+
+ nxagentGrabServerInfo.client = grab->client;
+ nxagentGrabServerInfo.grabstate = grab->grabstate;
+}
+
+#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..2dc0f5c02
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Init.h
@@ -0,0 +1,42 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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;
+
+extern ServerGrabInfoRec nxagentGrabServerInfo;
+
+#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..8db38892e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c
@@ -0,0 +1,1814 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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"
+
+#include "Shadow.h"
+
+#ifdef XKB
+
+#include "globals.h"
+#include "property.h"
+
+#include <X11/extensions/XKB.h>
+
+#define XKBSRV_NEED_FILE_FUNCS
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XKBconfig.h>
+
+#include "X11/extensions/XKBrules.h"
+
+#include "Xatom.h"
+
+static int nxagentXkbGetNames(char **rules, char **model, char **layout,
+ char **variant, char **options);
+
+static void nxagentKeycodeConversionSetup(void);
+
+#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 CARD8 nxagentConvertedKeycodes[] =
+{
+ /* evdev pc105*/
+ /* 0 */ 0,
+ /* 1 */ 1,
+ /* 2 */ 2,
+ /* 3 */ 3,
+ /* 4 */ 4,
+ /* 5 */ 5,
+ /* 6 */ 6,
+ /* 7 */ 7,
+ /* 8 */ 8,
+ /* 9 */ 9,
+ /* 10 */ 10,
+ /* 11 */ 11,
+ /* 12 */ 12,
+ /* 13 */ 13,
+ /* 14 */ 14,
+ /* 15 */ 15,
+ /* 16 */ 16,
+ /* 17 */ 17,
+ /* 18 */ 18,
+ /* 19 */ 19,
+ /* 20 */ 20,
+ /* 21 */ 21,
+ /* 22 */ 22,
+ /* 23 */ 23,
+ /* 24 */ 24,
+ /* 25 */ 25,
+ /* 26 */ 26,
+ /* 27 */ 27,
+ /* 28 */ 28,
+ /* 29 */ 29,
+ /* 30 */ 30,
+ /* 31 */ 31,
+ /* 32 */ 32,
+ /* 33 */ 33,
+ /* 34 */ 34,
+ /* 35 */ 35,
+ /* 36 */ 36,
+ /* 37 */ 37,
+ /* 38 */ 38,
+ /* 39 */ 39,
+ /* 40 */ 40,
+ /* 41 */ 41,
+ /* 42 */ 42,
+ /* 43 */ 43,
+ /* 44 */ 44,
+ /* 45 */ 45,
+ /* 46 */ 46,
+ /* 47 */ 47,
+ /* 48 */ 48,
+ /* 49 */ 49,
+ /* 50 */ 50,
+ /* 51 */ 51,
+ /* 52 */ 52,
+ /* 53 */ 53,
+ /* 54 */ 54,
+ /* 55 */ 55,
+ /* 56 */ 56,
+ /* 57 */ 57,
+ /* 58 */ 58,
+ /* 59 */ 59,
+ /* 60 */ 60,
+ /* 61 */ 61,
+ /* 62 */ 62,
+ /* 63 */ 63,
+ /* 64 */ 64,
+ /* 65 */ 65,
+ /* 66 */ 66,
+ /* 67 */ 67,
+ /* 68 */ 68,
+ /* 69 */ 69,
+ /* 70 */ 70,
+ /* 71 */ 71,
+ /* 72 */ 72,
+ /* 73 */ 73,
+ /* 74 */ 74,
+ /* 75 */ 75,
+ /* 76 */ 76,
+ /* 77 */ 77,
+ /* 78 */ 78,
+ /* 79 */ 79,
+ /* 80 */ 80,
+ /* 81 */ 81,
+ /* 82 */ 82,
+ /* 83 */ 83,
+ /* 84 */ 84,
+ /* 85 */ 85,
+ /* 86 */ 86,
+ /* 87 */ 87,
+ /* 88 */ 88,
+ /* 89 */ 89,
+ /* 90 */ 90,
+ /* 91 */ 91,
+ /* 92 */ 124,
+ /* 93 */ 93,
+ /* 94 */ 94,
+ /* 95 */ 95,
+ /* 96 */ 96,
+ /* 97 */ 211,
+ /* 98 */ 98,
+ /* 99 */ 99,
+ /* 100 */ 100,
+ /* 101 */ 208,
+ /* 102 */ 102,
+ /* 103 */ 103,
+ /* 104 */ 108,
+ /* 105 */ 109,
+ /* 106 */ 112,
+ /* 107 */ 111,
+ /* 108 */ 113,
+ /* 109 */ 109,
+ /* 110 */ 97,
+ /* 111 */ 98,
+ /* 112 */ 99,
+ /* 113 */ 100,
+ /* 114 */ 102,
+ /* 115 */ 103,
+ /* 116 */ 104,
+ /* 117 */ 105,
+ /* 118 */ 106,
+ /* 119 */ 107,
+ /* 120 */ 120,
+ /* 121 */ 121,
+ /* 122 */ 122,
+ /* 123 */ 123,
+ /* 124 */ 124,
+ /* 125 */ 126,
+ /* 126 */ 126,
+ /* 127 */ 110,
+ /* 128 */ 128,
+ /* 129 */ 129,
+ /* 130 */ 130,
+ /* 131 */ 131,
+ /* 132 */ 133,
+ /* 133 */ 115,
+ /* 134 */ 116,
+ /* 135 */ 117,
+ /* 136 */ 136,
+ /* 137 */ 137,
+ /* 138 */ 138,
+ /* 139 */ 139,
+ /* 140 */ 140,
+ /* 141 */ 141,
+ /* 142 */ 142,
+ /* 143 */ 143,
+ /* 144 */ 144,
+ /* 145 */ 145,
+ /* 146 */ 146,
+ /* 147 */ 147,
+ /* 148 */ 148,
+ /* 149 */ 149,
+ /* 150 */ 150,
+ /* 151 */ 151,
+ /* 152 */ 152,
+ /* 153 */ 153,
+ /* 154 */ 154,
+ /* 155 */ 155,
+ /* 156 */ 156,
+ /* 157 */ 157,
+ /* 158 */ 158,
+ /* 159 */ 159,
+ /* 160 */ 160,
+ /* 161 */ 161,
+ /* 162 */ 162,
+ /* 163 */ 163,
+ /* 164 */ 164,
+ /* 165 */ 165,
+ /* 166 */ 166,
+ /* 167 */ 167,
+ /* 168 */ 168,
+ /* 169 */ 169,
+ /* 170 */ 170,
+ /* 171 */ 171,
+ /* 172 */ 172,
+ /* 173 */ 173,
+ /* 174 */ 174,
+ /* 175 */ 175,
+ /* 176 */ 176,
+ /* 177 */ 177,
+ /* 178 */ 178,
+ /* 179 */ 179,
+ /* 180 */ 180,
+ /* 181 */ 181,
+ /* 182 */ 182,
+ /* 183 */ 183,
+ /* 184 */ 184,
+ /* 185 */ 185,
+ /* 186 */ 186,
+ /* 187 */ 187,
+ /* 188 */ 188,
+ /* 189 */ 189,
+ /* 190 */ 190,
+ /* 191 */ 118,
+ /* 192 */ 119,
+ /* 193 */ 120,
+ /* 194 */ 121,
+ /* 195 */ 122,
+ /* 196 */ 196,
+ /* 197 */ 197,
+ /* 198 */ 198,
+ /* 199 */ 199,
+ /* 200 */ 200,
+ /* 201 */ 201,
+ /* 202 */ 202,
+ /* 203 */ 93,
+ /* 204 */ 125,
+ /* 205 */ 156,
+ /* 206 */ 127,
+ /* 207 */ 128,
+ /* 208 */ 208,
+ /* 209 */ 209,
+ /* 210 */ 210,
+ /* 211 */ 211,
+ /* 212 */ 212,
+ /* 213 */ 213,
+ /* 214 */ 214,
+ /* 215 */ 215,
+ /* 216 */ 216,
+ /* 217 */ 217,
+ /* 218 */ 218,
+ /* 219 */ 219,
+ /* 220 */ 220,
+ /* 221 */ 221,
+ /* 222 */ 222,
+ /* 223 */ 223,
+ /* 224 */ 224,
+ /* 225 */ 225,
+ /* 226 */ 226,
+ /* 227 */ 227,
+ /* 228 */ 228,
+ /* 229 */ 229,
+ /* 230 */ 230,
+ /* 231 */ 231,
+ /* 232 */ 232,
+ /* 233 */ 233,
+ /* 234 */ 234,
+ /* 235 */ 235,
+ /* 236 */ 236,
+ /* 237 */ 237,
+ /* 238 */ 238,
+ /* 239 */ 239,
+ /* 240 */ 240,
+ /* 241 */ 241,
+ /* 242 */ 242,
+ /* 243 */ 243,
+ /* 244 */ 244,
+ /* 245 */ 245,
+ /* 246 */ 246,
+ /* 247 */ 247,
+ /* 248 */ 248,
+ /* 249 */ 249,
+ /* 250 */ 250,
+ /* 251 */ 251,
+ /* 252 */ 252,
+ /* 253 */ 253,
+ /* 254 */ 254,
+ /* 255 */ 255
+};
+
+static int nxagentKeycodeConversion = 0;
+
+CARD8 nxagentConvertKeycode(CARD8 k)
+{
+ if (nxagentKeycodeConversion != 0)
+ {
+ return nxagentConvertedKeycodes[k];
+ }
+ else
+ {
+ return k;
+ }
+}
+
+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 (keymap64 == 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<<j;
+
+ if (keycode > 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);
+
+ nxagentKeycodeConversionSetup();
+
+ if (xkb == NULL || xkb->geom == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No current keyboard.\n");
+ if (xkb == NULL)
+ {
+ fprintf(stderr, "nxagentKeyboardProc: xkb is null.\n");
+ }
+ else
+ {
+ fprintf(stderr, "nxagentKeyboardProc: xkb->geom is null.\n");
+ }
+ 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);
+
+ 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);
+
+ free(nxagentXkbConfigFilePath);
+
+ 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 (nxagentOption(Shadow) == 1 && pDev && pDev->key)
+ {
+ NXShadowInitKeymap(&(pDev->key->curKeySyms));
+ }
+
+ 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();
+ }
+}
+
+static int nxagentXkbGetNames(char **rules, char **model, char **layout,
+ char **variant, char **options)
+{
+ Atom atom;
+ #ifdef _XSERVER64
+ Atom64 type;
+ #else
+ Atom type;
+ #endif
+ int format;
+ unsigned long n;
+ unsigned long after;
+ char *data;
+ char *name;
+ Status result;
+
+ data = name = NULL;
+
+ *rules = NULL;
+ *model = NULL;
+ *layout = NULL;
+ *variant = NULL;
+ *options = NULL;
+
+ atom = XInternAtom(nxagentDisplay, "_XKB_RULES_NAMES", 1);
+
+ if (atom == 0)
+ {
+ return 0;
+ }
+
+ result = XGetWindowProperty(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ atom, 0, 256, 0, XA_STRING, &type, &format,
+ &n, &after, (unsigned char **)&data);
+
+ if (result !=Success || data == NULL)
+ {
+ return 0;
+ }
+
+ if ((after > 0) || (type != XA_STRING) || (format != 8))
+ {
+ if (data != NULL)
+ {
+ XFree(data);
+ return 0;
+ }
+ }
+
+ name = data;
+
+ if (name < data + n)
+ {
+ *rules = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *model = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *layout = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *variant = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *options = name;
+ name += strlen(name) + 1;
+ }
+
+ return n;
+}
+
+void nxagentKeycodeConversionSetup(void)
+{
+ char *drules = 0;
+ char *dmodel = 0;
+ char *dlayout = 0;
+ char *dvariant = 0;
+ char *doptions = 0;
+ unsigned int drulesLen;
+
+ nxagentKeycodeConversion = 0;
+
+ drulesLen = nxagentXkbGetNames(&drules, &dmodel, &dlayout,
+ &dvariant, &doptions);
+
+ #ifdef DEBUG
+ if (drulesLen != 0 && drules != NULL && dmodel != NULL)
+ {
+ fprintf(stderr, "nxagentKeycodeConversionSetup: "
+ "Remote: [%s,%s,%s,%s,%s].\n", drules, dmodel, dlayout,
+ dvariant, doptions);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentKeycodeConversionSetup: "
+ "Failed to retrieve remote rules.\n");
+ }
+ #endif
+
+ if (nxagentOption(ClientOs) == ClientOsLinux &&
+ drules != NULL && dmodel != NULL &&
+ (strcmp(drules, "evdev") == 0 ||
+ strcmp(dmodel, "evdev") == 0))
+ {
+ nxagentKeycodeConversion = 1;
+ }
+
+ if (drules != NULL)
+ {
+ XFree(drules);
+ }
+}
+
+void nxagentResetKeycodeConversion(void)
+{
+ int result;
+ XkbAgentInfoRec info;
+
+ result = XkbQueryExtension(nxagentDisplay, &info.Opcode, &info.EventBase,
+ &info.ErrorBase, &info.MajorVersion,
+ &info.MinorVersion);
+
+ if (result != 0)
+ {
+ nxagentKeycodeConversionSetup();
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentResetKeycodeConversion: "
+ "WARNING! Failed to query XKB extension.\n");
+ #endif
+
+ nxagentKeycodeConversion = 0;
+ }
+}
+
+#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..0e11a8a13
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.h
@@ -0,0 +1,118 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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);
+
+void nxagentResetKeycodeConversion(void);
+
+#endif
+
+CARD8 nxagentConvertKeycode(CARD8 k);
+
+#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..6c6e477ab
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c
@@ -0,0 +1,343 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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;
+
+#ifdef NX_DEBUG_INPUT
+int nxagentDebugInputDevices = 0;
+unsigned long nxagentLastInputDevicesDumpTime = 0;
+extern void nxagentDeactivateInputDevicesGrabs();
+#endif
+
+/*
+ * 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)
+ {
+ #ifdef DEBUG_TREE
+
+ case XK_q:
+ case XK_Q:
+ {
+ *result = doDebugTree;
+
+ break;
+ }
+
+ #endif /* DEBUG_TREE */
+
+ case XK_t:
+ case XK_T:
+ {
+ *result = doCloseSession;
+
+ break;
+ }
+ case XK_f:
+ case XK_F:
+ {
+ if (nxagentOption(Rootless) == False)
+ {
+ *result = doSwitchAllScreens;
+ }
+
+ 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
+
+ #ifdef NX_DEBUG_INPUT
+
+ case XK_X:
+ case XK_x:
+ {
+ /*
+ * Used to test the input devices state.
+ */
+
+ if (X -> type == KeyPress)
+ {
+ if (nxagentDebugInputDevices == 0)
+ {
+ fprintf(stderr, "Info: Turning input devices debug ON.\n");
+
+ nxagentDebugInputDevices = 1;
+ }
+ else
+ {
+ fprintf(stderr, "Info: Turning input devices debug OFF.\n");
+
+ nxagentDebugInputDevices = 0;
+
+ nxagentLastInputDevicesDumpTime = 0;
+ }
+ }
+
+ return 1;
+ }
+
+ case XK_Y:
+ case XK_y:
+ {
+ /*
+ * Used to deactivate input devices grab.
+ */
+
+ if (X -> type == KeyPress)
+ {
+ nxagentDeactivateInputDevicesGrabs();
+ }
+
+ return 1;
+ }
+
+ #endif
+ }
+ }
+ else if ((X -> state & nxagentAltMetaMask) &&
+ ((X -> state & (ControlMask | ShiftMask)) == (ControlMask |
+ ShiftMask)))
+ {
+ switch (sym)
+ {
+ case XK_f:
+ case XK_F:
+ {
+ if (nxagentOption(Rootless) == 0)
+ {
+ *result = doSwitchFullscreen;
+ }
+
+ break;
+ }
+ case XK_Left:
+ case XK_KP_Left:
+ {
+ if (nxagentOption(Rootless) == 0 &&
+ nxagentOption(DesktopResize) == 0)
+ {
+ *result = doViewportMoveLeft;
+ }
+
+ break;
+ }
+ case XK_Up:
+ case XK_KP_Up:
+ {
+ if (nxagentOption(Rootless) == 0 &&
+ nxagentOption(DesktopResize) == 0)
+ {
+ *result = doViewportMoveUp;
+ }
+
+ break;
+ }
+ case XK_Right:
+ case XK_KP_Right:
+ {
+ if (nxagentOption(Rootless) == 0 &&
+ nxagentOption(DesktopResize) == 0)
+ {
+ *result = doViewportMoveRight;
+ }
+
+ break;
+ }
+ case XK_Down:
+ case XK_KP_Down:
+ {
+ if (nxagentOption(Rootless) == 0 &&
+ nxagentOption(DesktopResize) == 0)
+ {
+ *result = doViewportMoveDown;
+ }
+
+ break;
+ }
+ }
+ }
+
+ 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..ef71a8851
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
@@ -0,0 +1,27 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..8446e6f55
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2001, 2011 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..aaa3430d6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Literals.h
@@ -0,0 +1,205 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..e9c739eeb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Millis.c
@@ -0,0 +1,70 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <time.h>
+#include <stdio.h>
+
+#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..69d247bbc
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Millis.h
@@ -0,0 +1,30 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <X11/extensions/composite.h>
+#include <X11/extensions/Xfixes.h>
+
+#endif
+
+#include <X11/Xfuncproto.h>
+
+/*
+ * 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 <X11/extensions/xfixeswire.h>
+
+#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 <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+
+#ifdef NXAGENT_SERVER
+#include "NXcompositeproto.h"
+#include "NXcomposite.h"
+#else
+#include <X11/extensions/compositeproto.h>
+#include <X11/extensions/Xcomposite.h>
+#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 <X11/Xmd.h>
+
+#ifdef NXAGENT_SERVER
+
+#include "NXcomposite.h"
+
+#else
+
+#include <X11/extensions/composite.h>
+
+#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..4f59b8098
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <stdio.h>
+int ProcInitialConnection();
+#endif
+
+#ifdef __sun
+#define False 0
+#define True 1
+#endif
+
+#define GC XlibGC
+#include <X11/Xlib.h>
+#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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client != NullClient)
+ {
+ if (client->lastDrawableID == 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; i<pDraw->pScreen->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; i<currentMaxClients; i++)
+ if (clients[i]) {
+ /* Make sure Retained clients are released. */
+ clients[i]->closeDownMode = 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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && (client->closeDownMode == 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; i<numScreens; i++)
+ {
+ register unsigned int j;
+ register xDepth *pDepth;
+
+ root->currentInputMask = 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..4f59b8098
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <stdio.h>
+int ProcInitialConnection();
+#endif
+
+#ifdef __sun
+#define False 0
+#define True 1
+#endif
+
+#define GC XlibGC
+#include <X11/Xlib.h>
+#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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client != NullClient)
+ {
+ if (client->lastDrawableID == 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; i<pDraw->pScreen->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; i<currentMaxClients; i++)
+ if (clients[i]) {
+ /* Make sure Retained clients are released. */
+ clients[i]->closeDownMode = 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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && (client->closeDownMode == 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; i<numScreens; i++)
+ {
+ register unsigned int j;
+ register xDepth *pDepth;
+
+ root->currentInputMask = 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 <stdio.h>
+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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client != NullClient)
+ {
+ if (client->lastDrawableID == 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; i<pDraw->pScreen->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; i<currentMaxClients; i++)
+ if (clients[i]) {
+ /* Make sure Retained clients are released. */
+ clients[i]->closeDownMode = 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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && (client->closeDownMode == 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; i<numScreens; i++)
+ {
+ register unsigned int j;
+ register xDepth *pDepth;
+
+ root->currentInputMask = 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..1cccfd972
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <stdio.h>
+#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..1cccfd972
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <stdio.h>
+#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 <stdio.h>
+#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..f697cf3ca
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 Button<n>MotionMasks are equal
+ * to the corresponding Button<n>Masks 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; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ }
+ else
+ {
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
+ FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ /* next call catches the root too, if the screen changed */
+ FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
+ NotifyNonlinearVirtual, FALSE);
+ }
+ /* Notify all the roots */
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
+ if (toWin == PointerRootWin)
+ (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
+ NotifyPointer, TRUE);
+ }
+ else
+ {
+ if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
+ {
+ if (fromWin == PointerRootWin)
+ FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+ TRUE);
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
+ NotifyNonlinearVirtual, TRUE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
+ NotifyPointer, FALSE);
+ }
+ else
+ {
+ if (IsParent(toWin, fromWin))
+ {
+ FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
+ FocusOutEvents(dev, fromWin->parent, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
+ if ((IsParent(toWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(fromWin, sprite.win)) &&
+ (!IsParent(sprite.win, fromWin)))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ else
+ if (IsParent(fromWin, toWin))
+ {
+ if ((IsParent(fromWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(toWin, sprite.win)) &&
+ (!IsParent(sprite.win, toWin)))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
+ (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
+ }
+ else
+ {
+ /* neither fromWin or toWin is child of other */
+ WindowPtr common = CommonAncestor(toWin, fromWin);
+ /* common == NullWindow ==> different screens */
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ if (fromWin->parent != NullWindow)
+ FocusOutEvents(dev, fromWin->parent, common, mode,
+ NotifyNonlinearVirtual, FALSE);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, common, toWin, toWin, mode,
+ NotifyNonlinearVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ }
+ }
+}
+
+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..f697cf3ca
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 Button<n>MotionMasks are equal
+ * to the corresponding Button<n>Masks 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; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ }
+ else
+ {
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
+ FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ /* next call catches the root too, if the screen changed */
+ FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
+ NotifyNonlinearVirtual, FALSE);
+ }
+ /* Notify all the roots */
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
+ if (toWin == PointerRootWin)
+ (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
+ NotifyPointer, TRUE);
+ }
+ else
+ {
+ if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
+ {
+ if (fromWin == PointerRootWin)
+ FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+ TRUE);
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
+ NotifyNonlinearVirtual, TRUE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
+ NotifyPointer, FALSE);
+ }
+ else
+ {
+ if (IsParent(toWin, fromWin))
+ {
+ FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
+ FocusOutEvents(dev, fromWin->parent, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
+ if ((IsParent(toWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(fromWin, sprite.win)) &&
+ (!IsParent(sprite.win, fromWin)))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ else
+ if (IsParent(fromWin, toWin))
+ {
+ if ((IsParent(fromWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(toWin, sprite.win)) &&
+ (!IsParent(sprite.win, toWin)))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
+ (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
+ }
+ else
+ {
+ /* neither fromWin or toWin is child of other */
+ WindowPtr common = CommonAncestor(toWin, fromWin);
+ /* common == NullWindow ==> different screens */
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ if (fromWin->parent != NullWindow)
+ FocusOutEvents(dev, fromWin->parent, common, mode,
+ NotifyNonlinearVirtual, FALSE);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, common, toWin, toWin, mode,
+ NotifyNonlinearVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ }
+ }
+}
+
+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 Button<n>MotionMasks are equal
+ * to the corresponding Button<n>Masks 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; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ }
+ else
+ {
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
+ FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ /* next call catches the root too, if the screen changed */
+ FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
+ NotifyNonlinearVirtual, FALSE);
+ }
+ /* Notify all the roots */
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
+ if (toWin == PointerRootWin)
+ (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
+ NotifyPointer, TRUE);
+ }
+ else
+ {
+ if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
+ {
+ if (fromWin == PointerRootWin)
+ FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+ TRUE);
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
+ NotifyNonlinearVirtual, TRUE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
+ NotifyPointer, FALSE);
+ }
+ else
+ {
+ if (IsParent(toWin, fromWin))
+ {
+ FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
+ FocusOutEvents(dev, fromWin->parent, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
+ if ((IsParent(toWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(fromWin, sprite.win)) &&
+ (!IsParent(sprite.win, fromWin)))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ else
+ if (IsParent(fromWin, toWin))
+ {
+ if ((IsParent(fromWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(toWin, sprite.win)) &&
+ (!IsParent(sprite.win, toWin)))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
+ (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
+ }
+ else
+ {
+ /* neither fromWin or toWin is child of other */
+ WindowPtr common = CommonAncestor(toWin, fromWin);
+ /* common == NullWindow ==> different screens */
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ if (fromWin->parent != NullWindow)
+ FocusOutEvents(dev, fromWin->parent, common, mode,
+ NotifyNonlinearVirtual, FALSE);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, common, toWin, toWin, mode,
+ NotifyNonlinearVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ }
+ }
+}
+
+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..1d86bf870
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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; i<NumExtensions; i++)
+ {
+ if ((strlen(extensions[i]->name) == 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; i<MAXSCREENS; i++)
+ {
+ register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i];
+
+ while (spentry->num)
+ {
+ 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; i<NumExtensions; i++)
+ {
+#ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ if (client->trustLevel == 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; i<NumExtensions; i++)
+ {
+ int len;
+#ifdef XCSECURITY
+ if (client->trustLevel == 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..1d86bf870
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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; i<NumExtensions; i++)
+ {
+ if ((strlen(extensions[i]->name) == 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; i<MAXSCREENS; i++)
+ {
+ register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i];
+
+ while (spentry->num)
+ {
+ 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; i<NumExtensions; i++)
+ {
+#ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ if (client->trustLevel == 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; i<NumExtensions; i++)
+ {
+ int len;
+#ifdef XCSECURITY
+ if (client->trustLevel == 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; i<NumExtensions; i++)
+ {
+ if ((strlen(extensions[i]->name) == 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; i<MAXSCREENS; i++)
+ {
+ register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i];
+
+ while (spentry->num)
+ {
+ 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; i<NumExtensions; i++)
+ {
+#ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ if (client->trustLevel == 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; i<NumExtensions; i++)
+ {
+ int len;
+#ifdef XCSECURITY
+ if (client->trustLevel == 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 <windowstr.h>
+#include <propertyst.h>
+#include <os.h>
+#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 <windowstr.h>
+#include <propertyst.h>
+#include <os.h>
+#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 <windowstr.h>
+#include <propertyst.h>
+#include <os.h>
+#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..22483b3fd
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..22483b3fd
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..9212bf438
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..9212bf438
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..0f122be4a
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..0f122be4a
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..09901ba9c
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..09901ba9c
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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, &reg, &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, &reg, &reg, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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, &reg, &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, &reg, &reg, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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, &reg, &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, &reg, &reg, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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..d32cdb6c4
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..d32cdb6c4
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..91eab0125
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..91eab0125
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..20a6bd6dc
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..20a6bd6dc
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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/NXrender.c b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c
new file mode 100644
index 000000000..43607ac08
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..43607ac08
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <assert.h>
+
+#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<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NullResource;
+ }
+ return TRUE;
+}
+
+
+static int
+#if NeedFunctionPrototypes
+Hash(int client, register XID id)
+#else
+Hash(client, id)
+ int client;
+ register XID id;
+#endif
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>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 <assert.h>
+
+#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<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NullResource;
+ }
+ return TRUE;
+}
+
+
+static int
+#if NeedFunctionPrototypes
+Hash(int client, register XID id)
+#else
+Hash(client, id)
+ int client;
+ register XID id;
+#endif
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>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 <assert.h>
+
+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<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NullResource;
+ }
+ return TRUE;
+}
+
+
+static int
+#if NeedFunctionPrototypes
+Hash(int client, register XID id)
+#else
+Hash(client, id)
+ int client;
+ register XID id;
+#endif
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>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 <sys/types.h>
+#ifndef Lynx
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#else
+#include <ipc.h>
+#include <shm.h>
+#endif
+#include <unistd.h>
+#include <sys/stat.h>
+#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 <sys/signal.h>
+
+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; i<pDraw->pScreen->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; i<pDraw->pScreen->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 <sys/types.h>
+#ifndef Lynx
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#else
+#include <ipc.h>
+#include <shm.h>
+#endif
+#include <unistd.h>
+#include <sys/stat.h>
+#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 <sys/signal.h>
+
+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; i<pDraw->pScreen->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; i<pDraw->pScreen->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 <sys/types.h>
+#ifndef Lynx
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#else
+#include <ipc.h>
+#include <shm.h>
+#endif
+#include <unistd.h>
+#include <sys/stat.h>
+#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 <sys/signal.h>
+
+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; i<pDraw->pScreen->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; i<pDraw->pScreen->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..95ecde951
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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; i<indent; i++) ErrorF( " ");
+ ErrorF( "%x\n", p1->drawable.id);
+ miPrintRegion(&p1->clipList);
+ PrintChildren(p2, indent+4);
+ p1 = p1->nextSib;
+ }
+}
+
+PrintWindowTree()
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i=0; i<screenInfo.numScreens; i++)
+ {
+ ErrorF( "WINDOW %d\n", i);
+ pWin = WindowTable[i];
+ miPrintRegion(&pWin->clipList);
+ 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; j<client->numSaved; 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; j<BitmapBytePad(32)*16; j++)
+ srcbits[j] = mskbits[j] = 0x0;
+ cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
+ if (cursor)
+ {
+ cursorID = FakeClientID(0);
+ if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
+ {
+ attributes[attri] = cursorID;
+ mask |= CWCursor;
+ }
+ else
+ cursor = 0;
+ }
+ else
+ {
+ xfree (srcbits);
+ xfree (mskbits);
+ }
+ }
+
+ pWin = savedScreenInfo[i].pWindow =
+ CreateWindow(savedScreenInfo[i].wid,
+ WindowTable[i],
+ -RANDOM_WIDTH, -RANDOM_WIDTH,
+ (unsigned short)screenInfo.screens[i]->width + 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..95ecde951
--- /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, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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; i<indent; i++) ErrorF( " ");
+ ErrorF( "%x\n", p1->drawable.id);
+ miPrintRegion(&p1->clipList);
+ PrintChildren(p2, indent+4);
+ p1 = p1->nextSib;
+ }
+}
+
+PrintWindowTree()
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i=0; i<screenInfo.numScreens; i++)
+ {
+ ErrorF( "WINDOW %d\n", i);
+ pWin = WindowTable[i];
+ miPrintRegion(&pWin->clipList);
+ 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; j<client->numSaved; 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; j<BitmapBytePad(32)*16; j++)
+ srcbits[j] = mskbits[j] = 0x0;
+ cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
+ if (cursor)
+ {
+ cursorID = FakeClientID(0);
+ if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
+ {
+ attributes[attri] = cursorID;
+ mask |= CWCursor;
+ }
+ else
+ cursor = 0;
+ }
+ else
+ {
+ xfree (srcbits);
+ xfree (mskbits);
+ }
+ }
+
+ pWin = savedScreenInfo[i].pWindow =
+ CreateWindow(savedScreenInfo[i].wid,
+ WindowTable[i],
+ -RANDOM_WIDTH, -RANDOM_WIDTH,
+ (unsigned short)screenInfo.screens[i]->width + 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; i<indent; i++) ErrorF( " ");
+ ErrorF( "%x\n", p1->drawable.id);
+ miPrintRegion(&p1->clipList);
+ PrintChildren(p2, indent+4);
+ p1 = p1->nextSib;
+ }
+}
+
+PrintWindowTree()
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i=0; i<screenInfo.numScreens; i++)
+ {
+ ErrorF( "WINDOW %d\n", i);
+ pWin = WindowTable[i];
+ miPrintRegion(&pWin->clipList);
+ 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; j<client->numSaved; 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; j<BitmapBytePad(32)*16; j++)
+ srcbits[j] = mskbits[j] = 0x0;
+ cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
+ if (cursor)
+ {
+ cursorID = FakeClientID(0);
+ if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
+ {
+ attributes[attri] = cursorID;
+ mask |= CWCursor;
+ }
+ else
+ cursor = 0;
+ }
+ else
+ {
+ xfree (srcbits);
+ xfree (mskbits);
+ }
+ }
+
+ pWin = savedScreenInfo[i].pWindow =
+ CreateWindow(savedScreenInfo[i].wid,
+ WindowTable[i],
+ -RANDOM_WIDTH, -RANDOM_WIDTH,
+ (unsigned short)screenInfo.screens[i]->width + 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..37b2c74fd
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.c
@@ -0,0 +1,755 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <config.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+/* we need to be able to manipulate the Display structure on events */
+#include <X11/Xlibint.h>
+#include <X11/extensions/render.h>
+#include <X11/extensions/Xrender.h>
+
+#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..160dc6517
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXxrandr.h
@@ -0,0 +1,168 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <X11/extensions/randr.h>
+
+#include <X11/Xfuncproto.h>
+
+_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..97ae77e29
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXxrandrint.h
@@ -0,0 +1,104 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include <X11/extensions/randr.h>
+#include <X11/extensions/randrproto.h>
+#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..5d7855667
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Options.c
@@ -0,0 +1,191 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#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;
+
+/*
+ * If this is set, print the geometry in the block handler.
+ */
+
+unsigned int nxagentPrintGeometryFlags = 0;
+/*
+ * 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.WMBorderWidth = -1;
+ nxagentOptions.WMTitleHeight = -1;
+
+ 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;
+
+ nxagentOptions.CopyBufferSize = COPY_UNLIMITED;
+}
+
+/*
+ * 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;
+
+ nxagentOptions.WMBorderWidth = -1;
+ nxagentOptions.WMTitleHeight = -1;
+}
+
+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..7850a0586
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Options.h
@@ -0,0 +1,417 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifndef __Options_H__
+#define __Options_H__
+
+#ifndef True
+#define True 1
+#endif
+
+#ifndef False
+#define False 0
+#endif
+
+#define UNDEFINED -1
+#define COPY_UNLIMITED -1
+
+extern unsigned int nxagentPrintGeometryFlags;
+
+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;
+
+ /*
+ * True if the fullscreen NX session will
+ * extend on all available screens.
+ */
+
+ int AllScreens;
+
+ /*
+ * 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 WMBorderWidth;
+ int WMTitleHeight;
+
+ 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;
+
+ /*
+ * Maximum number of bytes that can be pasted from
+ * an NX session into an external application.
+ */
+
+ int CopyBufferSize;
+
+} 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..d3ab9dd2f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixels.c
@@ -0,0 +1,384 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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..918d74dc7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixels.h
@@ -0,0 +1,180 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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.
+*/
+/*
+FIXME: Changed macro: NXAGENT_SHOULD_DEFER_COMPOSITE
+ to handle situation, when pSrc -> pDrawable
+ is NULL. This case happens with gradients
+ and solid fill.
+
+#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_COMPOSITE(pSrc, pMask, pDst) \
+ ((nxagentRenderVersionMajor == 0 && \
+ nxagentRenderVersionMinor == 8 && \
+ (pDst) -> pDrawable -> type == DRAWABLE_PIXMAP) || \
+ (nxagentOption(DeferLevel) >= 2 && \
+ nxagentOption(LinkType) < LINK_TYPE_ADSL) || \
+ (nxagentOption(DeferLevel) == 1 && \
+ (pDst) -> pDrawable -> type == DRAWABLE_PIXMAP && \
+ (((pSrc) -> pDrawable && nxagentDrawableStatus((pSrc) -> pDrawable) == NotSynchronized) || \
+ ((pMask) && nxagentDrawableStatus((pMask) -> pDrawable) == NotSynchronized))))
+
+
+#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..ad7e9c313
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixmap.c
@@ -0,0 +1,1646 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..98d5666d1
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h
@@ -0,0 +1,136 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..a751974af
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pointer.c
@@ -0,0 +1,191 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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
+
+/*
+ * The nxagentReversePointerMap array is used to
+ * memorize remote display pointer map.
+ */
+
+unsigned char nxagentReversePointerMap[MAXBUTTONS];
+
+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;
+ }
+
+ nxagentInitPointerMap();
+
+ 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;
+}
+
+void nxagentInitPointerMap(void)
+{
+ int numButtons;
+
+ int i;
+
+ unsigned char pointerMap[MAXBUTTONS];
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentInitPointerMap: Going to retrieve the "
+ "pointer map from remote display.\n");
+ #endif
+
+ numButtons = XGetPointerMapping(nxagentDisplay, pointerMap, MAXBUTTONS);
+
+ /*
+ * Computing revers pointer map.
+ */
+
+ for (i = 1; i <= numButtons; i++)
+ {
+ nxagentReversePointerMap[pointerMap[i - 1] - 1] = i;
+ }
+}
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..3b9ccce15
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pointer.h
@@ -0,0 +1,54 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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)
+
+/*
+ * The nxagentReversePointerMap array is used to
+ * memorize remote display pointer map.
+ */
+
+extern unsigned char nxagentReversePointerMap[MAXBUTTONS];
+
+void nxagentChangePointerControl(DeviceIntPtr pDev, PtrCtrl *ctrl);
+
+int nxagentPointerProc(DeviceIntPtr pDev, int onoff);
+
+void nxagentInitPointerMap(void);
+
+#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..90b80799c
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c
@@ -0,0 +1,812 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <signal.h>
+
+#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);
+
+extern void nxagentInitPointerMap(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)
+ {
+ #ifdef NX_DEBUG_INPUT
+ fprintf(stderr, "Session: Session suspended at '%s' timestamp [%lu].\n", GetTimeAsString(), GetTimeInMillis());
+ #else
+ fprintf(stderr, "Session: Session suspended at '%s'.\n", GetTimeAsString());
+ #endif
+ }
+
+ 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) == 1 &&
+ (nxagentKeyboard == NULL || nxagentOldKeyboard == NULL ||
+ strcmp(nxagentKeyboard, nxagentOldKeyboard) != 0 ||
+ strcmp(nxagentKeyboard, "query") == 0))
+ {
+ if (nxagentResetKeyboard() == 0)
+ {
+ #ifdef WARNING
+ if (nxagentVerbose == 1)
+ {
+ fprintf(stderr, "nxagentReconnect: Failed to reset keyboard device.\n");
+ }
+ #endif
+
+ failedStep = WINDOW_STEP;
+
+ goto nxagentReconnectError;
+ }
+ }
+ else
+ {
+ nxagentResetKeycodeConversion();
+ }
+
+ nxagentXkbState.Initialized = 0;
+
+ if (nxagentOldKeyboard != NULL)
+ {
+ xfree(nxagentOldKeyboard);
+
+ nxagentOldKeyboard = NULL;
+ }
+
+ nxagentInitPointerMap();
+
+ nxagentDeactivatePointerGrab();
+
+ nxagentWakeupByReconnect();
+
+ nxagentFreeGCList();
+
+ nxagentRedirectDefaultWindows();
+
+ if (nxagentResizeDesktopAtStartup || nxagentOption(Rootless) == True)
+ {
+ nxagentChangeScreenConfig(0, nxagentOption(RootWidth),
+ nxagentOption(RootHeight), 0, 0);
+
+ 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;
+ }
+
+ #ifdef NX_DEBUG_INPUT
+ fprintf(stderr, "Session: Session resumed at '%s' timestamp [%lu].\n", GetTimeAsString(), GetTimeInMillis());
+ #else
+ fprintf(stderr, "Session: Session resumed at '%s'.\n", GetTimeAsString());
+ #endif
+
+ 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();
+ }
+
+ if (nxagentOldKeyboard != NULL)
+ {
+ xfree(nxagentOldKeyboard);
+
+ nxagentOldKeyboard = NULL;
+ }
+
+ 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..c321bfada
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.h
@@ -0,0 +1,68 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..6c74c147f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Render.c
@@ -0,0 +1,3062 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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);
+
+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)
+{
+ if (pPicture == NULL || nxagentPicturePriv(pPicture) -> picture == 0)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyPicture: Going to destroy picture at [%p].\n",
+ (void *) pPicture);
+ #endif
+
+ 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
+
+ if (pSrc -> pDrawable != NULL)
+ {
+ 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.
+ */
+
+ if (pSrc -> pDrawable != NULL)
+ {
+ 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 (sizeImages > 0)
+ {
+ normalizedImages = xalloc(sizeImages);
+
+ if (normalizedImages != NULL)
+ {
+ memcpy(normalizedImages, images, sizeImages);
+
+ if (glyphDepths[glyphSet -> fdepth] == 1 &&
+ nxagentServerOrder() != BitmapBitOrder(nxagentDisplay))
+ {
+ 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;
+}
+
+void nxagentRenderCreateSolidFill(PicturePtr pPicture, xRenderColor *color)
+{
+ Picture id;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateSolidFill: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateSolidFill: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (color == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateSolidFill: WARNING! color pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ id = XRenderCreateSolidFill(nxagentDisplay, (XRenderColor *) color);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateSolidFill: Created solid fill xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
+void nxagentRenderCreateLinearGradient(PicturePtr pPicture, xPointFixed *p1,
+ xPointFixed *p2, int nStops,
+ xFixed *stops,
+ xRenderColor *colors)
+{
+ Picture id;
+
+ XLinearGradient linearGradient;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (p1 == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! p1 pointer is NULL.\n");
+ }
+
+ if (p2 == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! p2 pointer is NULL.\n");
+ }
+
+ if (stops == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! stops pointer is NULL.\n");
+ }
+
+ if (colors == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! colors pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ linearGradient.p1.x = (XFixed) p1 -> x;
+ linearGradient.p1.y = (XFixed) p1 -> y;
+ linearGradient.p2.x = (XFixed) p2 -> x;
+ linearGradient.p2.y = (XFixed) p2 -> y;
+
+ id = XRenderCreateLinearGradient(nxagentDisplay, &linearGradient,
+ (XFixed *) stops,
+ (XRenderColor *) colors, nStops);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: Created linear gradient xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
+void nxagentRenderCreateRadialGradient(PicturePtr pPicture, xPointFixed *inner,
+ xPointFixed *outer,
+ xFixed innerRadius,
+ xFixed outerRadius,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors)
+{
+ Picture id;
+
+ XRadialGradient radialGradient;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (inner == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! inner pointer is NULL.\n");
+ }
+
+ if (outer == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! outer pointer is NULL.\n");
+ }
+
+ if (stops == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! stops pointer is NULL.\n");
+ }
+
+ if (colors == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! colors pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ radialGradient.inner.x = (XFixed) inner -> x;
+ radialGradient.inner.y = (XFixed) inner -> y;
+ radialGradient.inner.radius = (XFixed) innerRadius;
+ radialGradient.outer.x = (XFixed) outer -> x;
+ radialGradient.outer.y = (XFixed) outer -> y;
+ radialGradient.outer.radius = (XFixed) outerRadius;
+
+ id = XRenderCreateRadialGradient(nxagentDisplay, &radialGradient,
+ (XFixed *) stops,
+ (XRenderColor *) colors, nStops);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: Created radial gradient xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
+void nxagentRenderCreateConicalGradient(PicturePtr pPicture,
+ xPointFixed *center,
+ xFixed angle, int nStops,
+ xFixed *stops,
+ xRenderColor *colors)
+{
+ Picture id;
+
+ XConicalGradient conicalGradient;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (center == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! center pointer is NULL.\n");
+ }
+
+ if (stops == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! stops pointer is NULL.\n");
+ }
+
+ if (colors == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! colors pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ conicalGradient.center.x = (XFixed) center -> x;
+ conicalGradient.center.y = (XFixed) center -> y;
+ conicalGradient.angle = (XFixed) angle;
+
+ id = XRenderCreateConicalGradient(nxagentDisplay, &conicalGradient,
+ (XFixed *) stops,
+ (XRenderColor *) colors, nStops);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: Created conical gradient xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
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..6f61ca85f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Render.h
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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);
+
+void nxagentDestroyPicture(PicturePtr pPicture);
+
+#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..74d2d1fe5
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Rootless.c
@@ -0,0 +1,1248 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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.
+ */
+
+typedef struct
+{
+ CARD32 flags;
+ CARD32 input;
+ CARD32 initial_state;
+ CARD32 icon_pixmap;
+ CARD32 icon_window;
+ INT32 icon_x;
+ INT32 icon_y;
+ CARD32 icon_mask;
+ CARD32 window_group;
+}
+nxagentWMHints;
+
+/*
+ * This structure is compatible with 32
+ * and 64 bit library interface. It has
+ * been copied from Xatomtype.h and it's
+ * a parameter of XChangeProperty().
+ */
+
+typedef struct
+{
+ unsigned long flags;
+ long input;
+ long initialState;
+ unsigned long iconPixmap;
+ unsigned long iconWindow;
+ long iconX;
+ long iconY;
+ unsigned long iconMask;
+ unsigned long windowGroup;
+}
+nxagentPropWMHints;
+
+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;
+ nxagentWMHints wmHints;
+ nxagentPropWMHints propHints;
+ 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 = *(nxagentWMHints*)value;
+
+ wmHints.flags |= InputHint;
+ wmHints.input = True;
+
+ /*
+ * Initialize the structure used in XChangeProperty().
+ */
+
+ propHints.flags = wmHints.flags;
+ propHints.input = (wmHints.input == True ? 1 : 0);
+ propHints.initialState = wmHints.initial_state;
+ propHints.iconPixmap = wmHints.icon_pixmap;
+ propHints.iconWindow = wmHints.icon_window;
+ propHints.iconX = wmHints.icon_x;
+ propHints.iconY = wmHints.icon_y;
+ propHints.iconMask = wmHints.icon_mask;
+ propHints.windowGroup = wmHints.window_group;
+
+ output = (char*) &propHints;
+ 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);
+ }
+
+ propHints.iconPixmap = nxagentPixmap(icon);
+ }
+ else
+ {
+ propHints.flags &= ~IconPixmapHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon pixmap %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) 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)
+ {
+ propHints.iconWindow = nxagentWindow(icon);
+ }
+ else
+ {
+ propHints.flags &= ~IconWindowHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon window %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) 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)
+ {
+ propHints.iconMask = nxagentPixmap(icon);
+ }
+ else
+ {
+ propHints.flags &= ~IconMaskHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon mask %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) 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)
+ {
+ propHints.windowGroup = nxagentWindow(window);
+ }
+ else
+ {
+ propHints.flags &= ~WindowGroupHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up window group %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) wmHints.window_group, propertyS, typeS,
+ (void *) pWin);
+ #endif
+ }
+ }
+ }
+ else if (strcmp(typeS, "ATOM") == 0)
+ {
+ XlibAtom *atoms = malloc(nUnits * sizeof(*atoms));
+ Atom *input = value;
+ char *atomName = NULL;
+ int i;
+ int j = 0;
+
+ freeMem = True;
+ export = True;
+ output = (char *) atoms;
+
+ for (i = 0; i < nUnits; i++)
+ {
+ /*
+ * Exporting the _NET_WM_PING property could
+ * result in rootless windows being grayed out
+ * when the compiz window manager is running.
+ *
+ * Better solution would probably be to handle
+ * the communication with the window manager
+ * instead of just getting rid of the property.
+ */
+
+ if ((atomName = NameForAtom(input[i])) != NULL &&
+ strcmp(atomName, "_NET_WM_PING") != 0)
+ {
+ atoms[j] = nxagentLocalToRemoteAtom(input[i]);
+
+ if (atoms[j] == None)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to convert local atom %ld [%s].\n",
+ (long int) input[i], validateString(atomName));
+ #endif
+ }
+
+ j++;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentExportProperty: WARNING! "
+ "Not exporting the _NET_WM_PING property.\n");
+ }
+ #endif
+ }
+
+ nUnits = j;
+ }
+ 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
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExportProperty: Property [%lu] format [%i] "
+ "units [%lu].\n", propertyX, format, nUnits);
+ #endif
+
+ if ((format >> 3) * nUnits + sizeof(xChangePropertyReq) <
+ (MAX_REQUEST_SIZE << 2))
+ {
+ XChangeProperty(nxagentDisplay, nxagentWindow(pWin), propertyX, typeX,
+ format, mode, (void*)output, nUnits);
+ }
+ else if (mode == PropModeReplace)
+ {
+ int n;
+ char *data;
+
+ XDeleteProperty(nxagentDisplay, nxagentWindow(pWin), propertyX);
+
+ data = (char *) output;
+
+ while (nUnits > 0)
+ {
+ if ((format >> 3) * nUnits + sizeof(xChangePropertyReq) <
+ (MAX_REQUEST_SIZE << 2))
+ {
+ n = nUnits;
+ }
+ else
+ {
+ n = ((MAX_REQUEST_SIZE << 2) - sizeof(xChangePropertyReq)) /
+ (format >> 3);
+ }
+
+ XChangeProperty(nxagentDisplay, nxagentWindow(pWin), propertyX,
+ typeX, format, PropModeAppend, (void*) data, n);
+
+ nUnits -= n;
+
+ data = (char *) data + n * (format >> 3);
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! "
+ "Property [%lu] too long.\n", propertyX);
+ #endif
+
+ goto nxagentExportPropertyError;
+ }
+
+ nxagentAddPropertyToList(propertyX, pWin);
+ }
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExportProperty: WARNING! Ignored ChangeProperty "
+ "on %swindow %x property %s type %s nUnits %ld format %d\n",
+ nxagentWindowTopLevel(pWin) ? "toplevel " : "",
+ nxagentWindow(pWin), validateString(propertyS), validateString(typeS),
+ nUnits, format);
+ #endif
+ }
+
+ nxagentExportPropertyError:
+
+ 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;
+ nxagentWMHints 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 = *(nxagentWMHints*)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 %d from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) 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 %x from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) 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 %x from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) 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 %x from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) 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..1ea258db3
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Rootless.h
@@ -0,0 +1,93 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..b847b08e6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.c
@@ -0,0 +1,4230 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <signal.h>
+
+#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 "mivalidate.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"
+
+#define GC XlibGC
+#define Font XlibFont
+#define KeySym XlibKeySym
+#define XID XlibXID
+#include <X11/Xlibint.h>
+#undef GC
+#undef Font
+#undef KeySym
+#undef XID
+
+#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);
+*/
+/*
+FIXME: We'll chech for ReparentNotify and LeaveNotify events after XReparentWindow()
+ in order to avoid the session window is iconified.
+ We could avoid the sesssion window is iconified when a LeaveNotify event is received,
+ so this check would be unnecessary.
+*/
+ struct timeval timeout;
+ int i;
+ XEvent e;
+
+ XReparentWindow(nxagentDisplay, nxagentFullscreenWindow,
+ RootWindow(nxagentDisplay, DefaultScreen(nxagentDisplay)), 0, 0);
+
+ for (i = 0; i < 100 && nxagentWMIsRunning; i++)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMaximizeToFullscreen: WARNING! Going to wait for the ReparentNotify event.\n");
+ #endif
+
+ if (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, ReparentNotify, &e))
+ {
+ break;
+ }
+
+ XSync(nxagentDisplay, 0);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 50 * 1000;
+
+ nxagentWaitEvents(nxagentDisplay, &timeout);
+ }
+
+ XMapRaised(nxagentDisplay, nxagentFullscreenWindow);
+
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+
+ while (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, LeaveNotify, &e));
+/*
+ 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 &&
+ (nxagentReconnectTrap == False || nxagentResizeDesktopAtStartup))
+ {
+ 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);
+
+ nxagentChangeOption(AllScreens, False);
+
+ nxagentFullscreenWindow = 0;
+
+ 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(AllScreens))
+ {
+ attributes.override_redirect = True;
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ /*
+ * 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(AllScreens) == 1 ? CWOverrideRedirect : 0);
+
+ attributes.background_pixel = nxagentBlackPixel;
+
+ nxagentGetDefaultEventMask((Mask*)&attributes.event_mask);
+
+ attributes.colormap = nxagentDefaultVisualColormap(nxagentDefaultVisual(pScreen));
+
+ if (nxagentOption(AllScreens) == 1)
+ {
+ attributes.override_redirect = True;
+ }
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ 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 || nxagentOption(Fullscreen) == 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(AllScreens))
+ {
+ if (nxagentReconnectTrap)
+ {
+ XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow, True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ }
+
+ 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);
+ }
+ 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;
+}
+
+/*
+ * This function comes from the xfree86 Xserver.
+ */
+
+static void nxagentSetRootClip (ScreenPtr pScreen, Bool enable)
+{
+ WindowPtr pWin = WindowTable[pScreen->myNum];
+ WindowPtr pChild;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool anyMarked = FALSE;
+ RegionPtr pOldClip = NULL, bsExposed;
+#ifdef DO_SAVE_UNDERS
+ Bool dosave = FALSE;
+#endif
+ WindowPtr pLayerWin;
+ BoxRec box;
+
+ if (WasViewable)
+ {
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ (void) (*pScreen->MarkOverlappedWindows)(pChild,
+ pChild,
+ &pLayerWin);
+ }
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ 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;
+ }
+ }
+
+ /*
+ * Use REGION_BREAK to avoid optimizations in ValidateTree
+ * that assume the root borderClip can't change well, normally
+ * it doesn't...)
+ */
+ if (enable)
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_INIT (pScreen, &pWin->winSize, &box, 1);
+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1);
+ if (WasViewable)
+ REGION_RESET(pScreen, &pWin->borderClip, &box);
+ pWin->drawable.width = pScreen->width;
+ pWin->drawable.height = pScreen->height;
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+ else
+ {
+ REGION_EMPTY(pScreen, &pWin->borderClip);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+
+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pWin->backStorage)
+ {
+ pOldClip = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, pOldClip, &pWin->clipList);
+ }
+
+ if (pWin->firstChild)
+ {
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
+ pWin->firstChild,
+ (WindowPtr *)NULL);
+ }
+ else
+ {
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ }
+
+#ifdef DO_SAVE_UNDERS
+ if (DO_SAVE_UNDERS(pWin))
+ {
+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin);
+ }
+#endif /* DO_SAVE_UNDERS */
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
+ }
+
+ if (pWin->backStorage && pOldClip &&
+ ((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)(pWin);
+#ifdef DO_SAVE_UNDERS
+ if (dosave)
+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
+#endif /* DO_SAVE_UNDERS */
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+ FlushAllOutput ();
+}
+
+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;
+
+ #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(RootX, (nxagentOption(Width) -
+ nxagentOption(RootWidth)) / 2);
+ nxagentChangeOption(RootY, (nxagentOption(Height) -
+ 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.
+ */
+
+ if ((nxagentOption(Fullscreen) == 0 && nxagentOption(AllScreens) == 0))
+ {
+ 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);
+
+ 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);
+
+ nxagentSetRootClip(pScreen, 1);
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(WindowTable[0]),
+ nxagentOption(RootX), nxagentOption(RootY));
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ /*
+ * Update pointer bounds.
+ */
+
+ ScreenRestructured(pScreen);
+
+ #ifdef TEST
+ nxagentPrintAgentGeometry("After Resize Screen", "nxagentResizeScreen:");
+ #endif
+
+ nxagentSetPrintGeometry(pScreen -> myNum);
+
+ 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 PANIIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! 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 PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! 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)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! The visual class of the remote "
+ "X server is not TrueColor.\n");
+ #endif
+
+ return -1;
+ }
+
+ if (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentShadowDisplay)) ->
+ class != TrueColor)
+ {
+ #ifdef PANIC
+
+ const char *className;
+
+ switch (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentShadowDisplay)) -> class)
+ {
+ case StaticGray:
+ {
+ className = "StaticGray";
+
+ break;
+ }
+ case StaticColor:
+ {
+ className = "StaticColor";
+
+ break;
+ }
+ case PseudoColor:
+ {
+ className = "PseudoColor";
+
+ break;
+ }
+ case DirectColor:
+ {
+ className = "DirectColor";
+
+ break;
+ }
+ case GrayScale:
+ {
+ className = "GrayScale";
+
+ break;
+ }
+ default:
+ {
+ className = "";
+
+ break;
+ }
+ }
+
+ fprintf(stderr, "nxagentShadowInit: PANIC! Cannot shadow the display. "
+ "%s visual class is not supported. Only TrueColor visuals "
+ "are supported.\n", className);
+
+ #endif /* #endif PANIC */
+
+ 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! Unable to shadow a %d bit "
+ "display with a 8 bit screen depth.\n", nxagentMasterDepth);
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 4;
+
+ break;
+ }
+ case 16:
+ {
+ if (nxagentShadowDepth > 16)
+ {
+ nxagentCheckDepth = 1;
+ }
+ else if (nxagentShadowDepth == 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a 16 bit "
+ "display with a 8 bit screen depth.\n");
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 2;
+
+ break;
+ }
+ case 8:
+ {
+ if (nxagentShadowDepth != 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a 8 bit "
+ "display with a %d bit screen depth.\n", nxagentShadowDepth);
+ #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);
+
+ if (nxagentRemoteMajor <= 3)
+ {
+ 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 */
+
+ if((x + width) > nxagentShadowWidth || (y + height) > nxagentShadowHeight)
+ {
+ /*
+ * Out of bounds. Maybe a resize of the master session is going on.
+ */
+
+ continue;
+ }
+
+ 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;
+}
+
+RRModePtr nxagentRRCustomMode = NULL;
+
+int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight)
+{
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ RROutputPtr output;
+ RRCrtcPtr crtc;
+ RRModePtr mode;
+ xRRModeInfo modeInfo;
+ char name[100];
+ int r, c, m;
+ int refresh = 60;
+ int doNotify = 1;
+
+ if (WindowTable[screen] == NULL)
+ {
+ return 0;
+ }
+
+ UpdateCurrentTime();
+
+ if (nxagentGrabServerInfo.grabstate == SERVER_GRABBED)
+ {
+ /*
+ * If any client grabbed the server it won't expect that screen
+ * configuration changes until it releases the grab. That could
+ * get an X error because available modes are chanded meanwhile.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: Cancel with grabbed server.\n");
+ #endif
+
+ return 0;
+ }
+
+ pScreen = WindowTable[screen] -> drawable.pScreen;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: Changing config to %dx%d.\n", width, height);
+ #endif
+
+ r = nxagentResizeScreen(pScreen, width, height, mmWidth, mmHeight);
+
+ if (r != 0)
+ {
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (pScrPriv)
+ {
+ output = RRFirstOutput(pScreen);
+
+ if (output && output -> crtc)
+ {
+ crtc = output -> crtc;
+
+ for (c = 0; c < pScrPriv -> numCrtcs; c++)
+ {
+ RRCrtcSet(pScrPriv -> crtcs[c], NULL, 0, 0, RR_Rotate_0, 0, NULL);
+ }
+
+ memset(&modeInfo, '\0', sizeof(modeInfo));
+ sprintf(name, "%dx%d", width, height);
+
+ modeInfo.width = width;
+ modeInfo.height = height;
+ modeInfo.hTotal = width;
+ modeInfo.vTotal = height;
+ modeInfo.dotClock = ((CARD32) width * (CARD32) height *
+ (CARD32) refresh);
+ modeInfo.nameLength = strlen(name);
+
+ if (nxagentRRCustomMode != NULL)
+ {
+ RROutputDeleteUserMode(output, nxagentRRCustomMode);
+ FreeResource(nxagentRRCustomMode -> mode.id, 0);
+
+ if (crtc != NULL && crtc -> mode == nxagentRRCustomMode)
+ {
+ RRCrtcSet(crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: "
+ "Going to destroy mode %p with refcnt %d.\n",
+ nxagentRRCustomMode, nxagentRRCustomMode->refcnt);
+ #endif
+
+ RRModeDestroy(nxagentRRCustomMode);
+ }
+
+ nxagentRRCustomMode = RRModeGet(&modeInfo, name);
+
+ RROutputAddUserMode(output, nxagentRRCustomMode);
+
+ RRCrtcSet(crtc, nxagentRRCustomMode, 0, 0, RR_Rotate_0, 1, &output);
+
+ RROutputChanged(output, 1);
+
+ doNotify = 0;
+ }
+
+ pScrPriv -> lastSetTime = currentTime;
+
+ pScrPriv->changed = 1;
+ pScrPriv->configChanged = 1;
+ }
+
+ if (doNotify
+)
+ {
+ RRScreenSizeNotify(pScreen);
+ }
+ }
+
+ return r;
+}
+
+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;
+
+ /*
+ * Limit the area to restore to the
+ * root window size.
+ */
+
+ REGION_INTERSECT(pWin -> pScreen, prgnRestore, prgnRestore,
+ &WindowTable[pWin -> drawable.pScreen -> myNum] -> winSize);
+
+ 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 / nxagentShadowWidth,
+ nxagentOption(Height) * 1.0 / nxagentShadowHeight);
+
+ 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, &region, &box, 1);
+
+ nxagentMarkCorruptedRegion((DrawablePtr)nxagentShadowPixmapPtr, &region);
+
+ REGION_UNINIT(pScreen, &region);
+}
+
+void nxagentPrintGeometry()
+{
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (nxagentPrintGeometryFlags && (1 << i))
+ {
+ fprintf(stderr, "Info: Screen [%d] resized to geometry [%dx%d] "
+ "fullscreen [%d].\n", i, screenInfo.screens[i] -> width,
+ screenInfo.screens[i] -> height,
+ nxagentOption(Fullscreen));
+ }
+ }
+
+ nxagentPrintGeometryFlags = 0;
+}
+
+#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..aab3ba19c
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.h
@@ -0,0 +1,137 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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
+
+#define nxagentSetPrintGeometry(screen) \
+ nxagentPrintGeometryFlags = (1 << (screen));
+
+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);
+
+void nxagentPrintGeometry();
+
+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 nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight);
+
+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..235c48c23
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Splash.c
@@ -0,0 +1,335 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..f7ba6c2e2
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Splash.h
@@ -0,0 +1,45 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..4cc2ea607
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Split.c
@@ -0,0 +1,1248 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..2be449a18
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Split.h
@@ -0,0 +1,84 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..6bce2eaeb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/TestExt.c
@@ -0,0 +1,83 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xlib.h>
+#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..f5e6bde0e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.c
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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;
+
+/*
+ * Set to avoid CapsLock synchronization
+ * problems when CapsLock is the first
+ * key to be pressed in the session.
+ */
+
+int nxagentXkbCapsTrap = 0;
+
+/*
+ * Set to avoid NumLock synchronization
+ * problems when NumLock is the first
+ * key to be pressed in the session.
+ */
+
+int nxagentXkbNumTrap = 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..9258e3b67
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.h
@@ -0,0 +1,116 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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;
+
+/*
+ * Set to avoid CapsLock synchronization
+ * problems when CapsLock is the first
+ * key to be pressed in the session.
+ */
+
+extern int nxagentXkbCapsTrap;
+
+/*
+ * Set to avoid NumLock synchronization
+ * problems when NumLock is the first
+ * key to be pressed in the session.
+ */
+
+extern int nxagentXkbNumTrap;
+
+#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..f5bd55d8b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Utils.h
@@ -0,0 +1,39 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..b086c0e9a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Visual.c
@@ -0,0 +1,159 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..8436f79ad
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Visual.h
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..988193609
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Window.c
@@ -0,0 +1,3876 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <unistd.h>
+
+#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)
+{
+ XEvent e;
+
+ if (nxagentOption(Rootless) == 1)
+ {
+ return;
+ }
+
+ if (switchOn == 0)
+ {
+ nxagentWMDetect();
+
+ /*
+ * The smart scheduler could be stopped while
+ * waiting for the reply. In this case we need
+ * to yield explicitly to avoid to be stuck in
+ * the dispatch loop forever.
+ */
+
+ isItTimeToYield = 1;
+
+ if (nxagentWMIsRunning == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "Warning: Can't switch to window mode, no window manager "
+ "has been detected.\n");
+ #endif
+
+ return;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSwitchFullscreen: Switching to %s mode.\n",
+ switchOn ? "fullscreen" : "windowed");
+ #endif
+
+ nxagentChangeOption(Fullscreen, switchOn);
+
+ memset(&e, 0, sizeof(e));
+
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = nxagentAtoms[13]; /* _NET_WM_STATE */
+ e.xclient.display = nxagentDisplay;
+ e.xclient.window = nxagentDefaultWindows[pScreen -> myNum];
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = nxagentOption(Fullscreen) ? 1 : 0;
+ e.xclient.data.l[1] = nxagentAtoms[14]; /* _NET_WM_STATE_FULLSCREEN */
+
+ XSendEvent(nxagentDisplay, DefaultRootWindow(nxagentDisplay), False,
+ SubstructureRedirectMask, &e);
+
+ if (switchOn == 1)
+ {
+ nxagentFullscreenWindow = nxagentDefaultWindows[pScreen -> myNum];
+
+ nxagentGrabPointerAndKeyboard(NULL);
+ }
+ else
+ {
+ nxagentFullscreenWindow = None;
+
+ nxagentUngrabPointerAndKeyboard(NULL);
+ }
+}
+
+void nxagentSwitchAllScreens(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);
+
+ XReparentWindow(nxagentDisplay, w, DefaultRootWindow(nxagentDisplay), 0, 0);
+
+ 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, "nxagentSwitchAllScreens: 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);
+ nxagentChangeOption(AllScreens, 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)
+ {
+ nxagentChangeScreenConfig(0, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)),
+ HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), 0, 0);
+ }
+ else
+ {
+ nxagentShadowAdaptToRatio();
+ }
+ }
+ }
+ else
+ {
+ /*
+ * We have waited for a reparent event unsuccessfully.
+ * Something happened to the window manager.
+ */
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSwitchAllScreens: 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 propagate device settings to the X server if no WM is running.
+ */
+
+ /*
+ * Change to windowed mode.
+ */
+
+ nxagentChangeOption(Fullscreen, False);
+ nxagentChangeOption(AllScreens, False);
+
+ XDestroyWindow(nxagentDisplay, nxagentIconWindow);
+
+ nxagentIconWindow = nxagentFullscreenWindow = None;
+
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ nxagentChangeOption(RootWidth, nxagentOption(SavedRootWidth));
+ nxagentChangeOption(RootHeight, nxagentOption(SavedRootHeight));
+
+ if (nxagentOption(Shadow) == 0)
+ {
+ nxagentChangeScreenConfig(0, nxagentOption(RootWidth),
+ nxagentOption(RootHeight), 0, 0);
+ }
+ }
+
+ if (nxagentOption(WMBorderWidth) > 0 && nxagentOption(WMTitleHeight) > 0)
+ {
+ nxagentChangeOption(X, nxagentOption(SavedX) -
+ nxagentOption(WMBorderWidth));
+ nxagentChangeOption(Y, nxagentOption(SavedY) -
+ nxagentOption(WMTitleHeight));
+ }
+ else
+ {
+ 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));
+
+ nxagentSetPrintGeometry(pScreen -> myNum);
+}
+
+#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;
+ int offX, offY;
+ int i, j;
+
+ offX = nxagentWindowPriv(pWin)->x - pWin->origin.x;
+ offY = nxagentWindowPriv(pWin)->y - pWin->origin.y;
+
+ 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
+
+ if (pWin->bitGravity == StaticGravity &&
+ ((mask & CWX) || (mask & CWY)) &&
+ ((mask & CWWidth) || (mask & CWHeight)))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Window has StaticGravity. Going to translate Expose events by offset [%d, %d].\n",
+ offX, offY);
+ #endif
+
+ nxagentAddStaticResizedWindow(pWin, XNextRequest(nxagentDisplay), offX, offY);
+
+ for (j = 0; j < nxagentExposeQueue.length; j++)
+ {
+ i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
+
+ if (nxagentExposeQueue.exposures[i].pWindow == pWin &&
+ nxagentExposeQueue.exposures[i].remoteRegion != NullRegion)
+ {
+ REGION_TRANSLATE(pWin -> drawable.pScreen, nxagentExposeQueue.exposures[i].remoteRegion, offX, offY);
+ }
+ }
+ }
+
+ 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]);
+
+ if (nxagentOption(Fullscreen) == 1 && nxagentWMIsRunning == 1)
+ {
+ nxagentMaximizeToFullScreen(pScreen);
+ }
+ }
+
+ /*
+ * 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;
+
+ #ifdef _XSERVER64
+
+ unsigned char *data64 = NULL;
+ unsigned int i;
+
+ #endif
+
+ hints.flags = 0;
+
+ ret = GetWindowProperty(pWin,
+ XA_WM_NORMAL_HINTS,
+ 0, sizeof(XSizeHints),
+ False, XA_WM_SIZE_HINTS,
+ &type, &format, &nItems, &bytesLeft, &data);
+
+ /*
+ * 72 is the number of bytes returned by
+ * sizeof(XSizeHints) on 32 bit platforms.
+ */
+
+ if (ret == Success &&
+ ((format >> 3) * nItems) == 72 &&
+ 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
+
+ #ifdef _XSERVER64
+
+ data64 = (unsigned char *) malloc(sizeof(XSizeHints) + 4);
+
+ for (i = 0; i < 4; i++)
+ {
+ *(data64 + i) = *(data + i);
+ }
+
+ *(((int *) data64) + 1) = 0;
+
+ for (i = 8; i < sizeof(XSizeHints) + 4; i++)
+ {
+ *(data64 + i) = *(data + i - 4);
+ }
+
+ props = (XSizeHints *) data64;
+
+ #else
+
+ props = (XSizeHints *) data;
+
+ #endif /* _XSERVER64 */
+
+ 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);
+
+ #ifdef _XSERVER64
+
+ if (data64 != NULL)
+ {
+ free(data64);
+ }
+
+ #endif
+ }
+ }
+
+ 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 nxagentAddStaticResizedWindow(WindowPtr pWin, unsigned long sequence, int offX, int offY)
+{
+ if (nxagentStaticResizedWindowList == NULL)
+ {
+ nxagentStaticResizedWindowList = malloc(sizeof(StaticResizedWindowStruct));
+ nxagentStaticResizedWindowList -> next = NULL;
+ nxagentStaticResizedWindowList -> prev = NULL;
+ }
+ else
+ {
+ StaticResizedWindowStruct *tmp;
+
+ tmp = malloc(sizeof(StaticResizedWindowStruct));
+
+ tmp -> next = nxagentStaticResizedWindowList;
+ nxagentStaticResizedWindowList -> prev = tmp;
+ tmp -> prev = NULL;
+ nxagentStaticResizedWindowList = tmp;
+ }
+
+ nxagentStaticResizedWindowList -> pWin = pWin;
+ nxagentStaticResizedWindowList -> sequence = sequence;
+ nxagentStaticResizedWindowList -> offX = offX;
+ nxagentStaticResizedWindowList -> offY = offY;
+}
+
+void nxagentDeleteStaticResizedWindow(unsigned long sequence)
+{
+ StaticResizedWindowStruct *index, *previous, *tmp;
+
+ index = nxagentStaticResizedWindowList;
+
+ while (index)
+ {
+ if (index -> sequence <= sequence)
+ {
+ if (index -> prev == NULL && index -> next == NULL)
+ {
+ free(nxagentStaticResizedWindowList);
+ nxagentStaticResizedWindowList = NULL;
+
+ return;
+ }
+ else if (index -> prev == NULL)
+ {
+ tmp = nxagentStaticResizedWindowList;
+ index = nxagentStaticResizedWindowList = tmp -> next;
+ free(tmp);
+ nxagentStaticResizedWindowList -> 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;
+}
+
+StaticResizedWindowStruct *nxagentFindStaticResizedWindow(unsigned long sequence)
+{
+ StaticResizedWindowStruct *index;
+ StaticResizedWindowStruct *ret = NULL;
+
+ if (nxagentStaticResizedWindowList == NULL)
+ {
+ return NULL;
+ }
+
+ index = nxagentStaticResizedWindowList;
+
+ while (index && index -> sequence > sequence)
+ {
+ ret = index;
+ index = index -> next;
+ }
+
+ return ret;
+}
+
+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..3ca74ba8e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Windows.h
@@ -0,0 +1,320 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 nxagentSwitchAllScreens(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;
+
+typedef struct _StaticResizedWindow
+{
+ WindowPtr pWin;
+ struct _StaticResizedWindow *next;
+ struct _StaticResizedWindow *prev;
+ unsigned long sequence;
+ int offX;
+ int offY;
+} StaticResizedWindowStruct;
+
+StaticResizedWindowStruct *nxagentStaticResizedWindowList;
+
+void nxagentPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind);
+
+void nxagentFlushConfigureWindow(void);
+
+void nxagentAddConfiguredWindow(WindowPtr pWin, unsigned int valuemask);
+
+void nxagentDeleteConfiguredWindow(WindowPtr pWin);
+
+void nxagentAddStaticResizedWindow(WindowPtr pWin, unsigned long sequence, int offX, int offY);
+
+void nxagentDeleteStaticResizedWindow(unsigned long sequence);
+
+StaticResizedWindowStruct *nxagentFindStaticResizedWindow(unsigned long sequence);
+
+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..cf5d48ba2
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c
@@ -0,0 +1,2073 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include <X11/fonts/font.h>
+#include "dixfontstr.h"
+#include <X11/fonts/fontstruct.h>
+#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, &region, pBox, 1);
+#if DAMAGE_DEBUG_ENABLE
+ _damageDamageRegion (pDrawable, &region, TRUE, subWindowMode, where);
+#else
+ damageDamageRegion (pDrawable, &region, TRUE, subWindowMode);
+#endif
+ REGION_UNINIT (pDrawable->pScreen, &region);
+}
+
+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..cf5d48ba2
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdamage.c.NX.original
@@ -0,0 +1,2073 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include <X11/fonts/font.h>
+#include "dixfontstr.h"
+#include <X11/fonts/fontstruct.h>
+#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, &region, pBox, 1);
+#if DAMAGE_DEBUG_ENABLE
+ _damageDamageRegion (pDrawable, &region, TRUE, subWindowMode, where);
+#else
+ damageDamageRegion (pDrawable, &region, TRUE, subWindowMode);
+#endif
+ REGION_UNINIT (pDrawable->pScreen, &region);
+}
+
+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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include <X11/fonts/font.h>
+#include "dixfontstr.h"
+#include <X11/fonts/fontstruct.h>
+#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, &region, pBox, 1);
+#if DAMAGE_DEBUG_ENABLE
+ _damageDamageRegion (pDrawable, &region, TRUE, subWindowMode, where);
+#else
+ damageDamageRegion (pDrawable, &region, TRUE, subWindowMode);
+#endif
+ REGION_UNINIT (pDrawable->pScreen, &region);
+}
+
+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..69ad30d2d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c
@@ -0,0 +1,4679 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#ifdef PANORAMIX_DEBUG
+#include <stdio.h>
+int ProcInitialConnection();
+#endif
+
+#ifdef __sun
+#define False 0
+#define True 1
+#endif
+
+#define GC XlibGC
+#include <X11/Xlib.h>
+#undef GC
+
+#include "windowstr.h"
+#include <X11/fonts/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 <X11/extensions/security.h>
+#endif
+#ifdef XAPPGROUP
+#include <X11/extensions/Xagsrv.h>
+#endif
+#ifdef XKB
+#define XKB_IN_SERVER
+#include "inputstr.h"
+#include <X11/extensions/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"
+#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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client != NullClient)
+ {
+ if (client->lastDrawableID == 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.
+ */
+
+ #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;
+ }
+
+ if (serverGeneration > nxagentMaxAllowedResets &&
+ nxagentSessionState == SESSION_STARTING &&
+ (nxagentOption(Xdmcp) == 0 || nxagentXdmcpUp == 1))
+ {
+ #ifdef NX_DEBUG_INPUT
+ fprintf(stderr, "Session: Session started at '%s' timestamp [%lu].\n",
+ GetTimeAsString(), GetTimeInMillis());
+ #else
+ fprintf(stderr, "Session: Session started at '%s'.\n",
+ GetTimeAsString());
+ #endif
+
+ nxagentSessionState = SESSION_UP;
+ }
+
+ #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; i<pDraw->pScreen->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;
+ }
+
+ SetScreenSaverTimer();
+ }
+ #ifdef TEST
+
+ else
+ {
+ fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n",
+ nxagentOption(Timeout));
+ }
+
+ #endif
+
+ 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; i<currentMaxClients; i++)
+ if (clients[i]) {
+ /* Make sure Retained clients are released. */
+ clients[i]->closeDownMode = 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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && (client->closeDownMode == 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; i<numScreens; i++)
+ {
+ register unsigned int j;
+ register xDepth *pDepth;
+
+ root->currentInputMask = 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..69ad30d2d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.NX.original
@@ -0,0 +1,4679 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#ifdef PANORAMIX_DEBUG
+#include <stdio.h>
+int ProcInitialConnection();
+#endif
+
+#ifdef __sun
+#define False 0
+#define True 1
+#endif
+
+#define GC XlibGC
+#include <X11/Xlib.h>
+#undef GC
+
+#include "windowstr.h"
+#include <X11/fonts/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 <X11/extensions/security.h>
+#endif
+#ifdef XAPPGROUP
+#include <X11/extensions/Xagsrv.h>
+#endif
+#ifdef XKB
+#define XKB_IN_SERVER
+#include "inputstr.h"
+#include <X11/extensions/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"
+#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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client != NullClient)
+ {
+ if (client->lastDrawableID == 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.
+ */
+
+ #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;
+ }
+
+ if (serverGeneration > nxagentMaxAllowedResets &&
+ nxagentSessionState == SESSION_STARTING &&
+ (nxagentOption(Xdmcp) == 0 || nxagentXdmcpUp == 1))
+ {
+ #ifdef NX_DEBUG_INPUT
+ fprintf(stderr, "Session: Session started at '%s' timestamp [%lu].\n",
+ GetTimeAsString(), GetTimeInMillis());
+ #else
+ fprintf(stderr, "Session: Session started at '%s'.\n",
+ GetTimeAsString());
+ #endif
+
+ nxagentSessionState = SESSION_UP;
+ }
+
+ #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; i<pDraw->pScreen->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;
+ }
+
+ SetScreenSaverTimer();
+ }
+ #ifdef TEST
+
+ else
+ {
+ fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n",
+ nxagentOption(Timeout));
+ }
+
+ #endif
+
+ 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; i<currentMaxClients; i++)
+ if (clients[i]) {
+ /* Make sure Retained clients are released. */
+ clients[i]->closeDownMode = 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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && (client->closeDownMode == 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; i<numScreens; i++)
+ {
+ register unsigned int j;
+ register xDepth *pDepth;
+
+ root->currentInputMask = 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 <dix-config.h>
+#endif
+
+#ifdef PANORAMIX_DEBUG
+#include <stdio.h>
+int ProcInitialConnection();
+#endif
+
+#include "windowstr.h"
+#include <X11/fonts/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 <X11/extensions/security.h>
+#endif
+#ifdef XAPPGROUP
+#include <X11/extensions/Xagsrv.h>
+#endif
+#ifdef XKB
+#define XKB_IN_SERVER
+#include "inputstr.h"
+#include <X11/extensions/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;
+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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client != NullClient)
+ {
+ if (client->lastDrawableID == 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; i<pDraw->pScreen->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; i<currentMaxClients; i++)
+ if (clients[i]) {
+ /* Make sure Retained clients are released. */
+ clients[i]->closeDownMode = 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; i<currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && (client->closeDownMode == 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; i<numScreens; i++)
+ {
+ register unsigned int j;
+ register xDepth *pDepth;
+
+ root->currentInputMask = 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..3234c9929
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c
@@ -0,0 +1,2805 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/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 <stdio.h>
+#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:
+
+ strncpy(_NXFontPath, path, 1023);
+ _NXFontPath[1023] = '\0';
+
+#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 <X11/extensions/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(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;
+ }
+ /* check values for firstCol, lastCol, firstRow, and lastRow */
+ if (pfont->info.firstCol > pfont->info.lastCol ||
+ pfont->info.firstRow > pfont->info.lastRow ||
+ pfont->info.lastCol - pfont->info.firstCol > 255) {
+ err = AllocError;
+ 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..04fc047fc
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.NX.original
@@ -0,0 +1,2804 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/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 <stdio.h>
+#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 <X11/extensions/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(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;
+ }
+ /* check values for firstCol, lastCol, firstRow, and lastRow */
+ if (pfont->info.firstCol > pfont->info.lastCol ||
+ pfont->info.firstRow > pfont->info.lastRow ||
+ pfont->info.lastCol - pfont->info.firstCol > 255) {
+ err = AllocError;
+ 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..2c5874e8d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXdixfonts.c.X.original
@@ -0,0 +1,2150 @@
+/* $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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/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 <stdio.h>
+#endif
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#endif
+
+#ifdef LBX
+#include "lbxserve.h"
+#endif
+
+#ifdef XF86BIGFONT
+#define _XF86BIGFONT_SERVER_
+#include <X11/extensions/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(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;
+ }
+ /* check values for firstCol, lastCol, firstRow, and lastRow */
+ if (pfont->info.firstCol > pfont->info.lastCol ||
+ pfont->info.firstRow > pfont->info.lastRow ||
+ pfont->info.lastCol - pfont->info.firstCol > 255) {
+ err = AllocError;
+ 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..c5593adbb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c
@@ -0,0 +1,5044 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "Xlib.h"
+#include "misc.h"
+#include "resource.h"
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/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 <X11/extensions/XKBsrv.h>
+extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
+#endif
+
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/security.h>
+#endif
+
+#ifdef XEVIE
+extern WindowPtr *WindowTable;
+extern int xevieFlag;
+extern int xevieClientIndex;
+extern DeviceIntPtr xeviemouse;
+extern DeviceIntPtr xeviekb;
+extern Mask xevieMask;
+extern Mask xevieFilters[128];
+extern int xevieEventSent;
+extern int xevieKBEventSent;
+int xeviegrabState = 0;
+xEvent *xeviexE;
+#endif
+
+#include <X11/extensions/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"
+#include "Args.h"
+
+#ifdef NX_DEBUG_INPUT
+extern int nxagentDebugInput;
+extern int nxagentDebugInputDevices;
+#endif
+
+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 Button<n>MotionMasks are equal
+ * to the corresponding Button<n>Masks 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 NX_DEBUG_INPUT
+ if (grab && nxagentDebugInput && grab->window)
+ {
+ fprintf(stderr, "TryClientEvents: Grab window is [0x%x].\n",
+ (unsigned int)grab->window->drawable.id);
+ if (!SameClient(grab, client))
+ fprintf(stderr, "TryClientEvents: Events are going to be "
+ "discarded.\n");
+ }
+#endif
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ fprintf(stderr, "Event([%d, %d], mask=0x%x), client=%d",
+ pEvents->u.u.type, pEvents->u.u.detail, (unsigned int)mask,
+ client->index);
+#else
+ if (debug_events) ErrorF(
+ "Event([%d, %d], mask=0x%x), client=%d",
+ pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
+#endif
+#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)
+ {
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr,"\nmotionHintWindow == keyButtonPointer.event\n");
+ }
+#else
+ if (debug_events) ErrorF("\n");
+ fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n");
+#endif
+#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);
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ fprintf(stderr, " delivered\n");
+#else
+ if (debug_events) ErrorF( " delivered\n");
+#endif
+#endif
+ return 1;
+ }
+ else
+ {
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ fprintf(stderr, "\n");
+#else
+ if (debug_events) ErrorF("\n");
+#endif
+#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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "DeliverEventsToWindow: Activating passive grab on pointer.\n");
+ }
+ #endif
+ (*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
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "CheckPassiveGrabsOnWindow: Activating passive grab on %s.\n",
+ device == inputInfo.keyboard ? "keyboard" : "pointer");
+ }
+ #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)
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcessKeyboardEvent: Deactivating grab on keyboard.\n");
+ }
+ #endif
+ (*keybd->DeactivateGrab)(keybd);
+ #ifdef NX_DEBUG_INPUT
+ }
+ #endif
+}
+
+#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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Going to send XEVIE event.\n");
+ }
+ #endif
+ 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
+ #ifdef NX_DEBUG_INPUT
+ if (xE->u.u.detail == 0)
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0"
+ " for ButtonPress.\n");
+ }
+ return;
+ }
+ #else
+ if (xE->u.u.detail == 0)
+ return;
+ #endif
+ if (xE->u.u.detail <= 5)
+ butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
+ filters[MotionNotify] = Motion_Filter(butc);
+ if (!grab)
+ #ifdef NX_DEBUG_INPUT
+ if (CheckDeviceGrabs(mouse, xE, 0, count))
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: CheckDeviceGrabs"
+ " returned True for ButtonPress.\n");
+ }
+ return;
+ }
+ #else
+ if (CheckDeviceGrabs(mouse, xE, 0, count))
+ return;
+ #endif
+ 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
+ #ifdef NX_DEBUG_INPUT
+ if (xE->u.u.detail == 0)
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0"
+ " for ButtonRelease.\n");
+ }
+ return;
+ }
+ #else
+ if (xE->u.u.detail == 0)
+ return;
+ #endif
+ 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");
+ }
+ }
+ #ifdef NX_DEBUG_INPUT
+ else if (!CheckMotion(xE))
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: CheckMotion returned False"
+ " for MotionNotify.\n");
+ }
+ return;
+ }
+ if (grab)
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Going to deliver grabbed "
+ "events (count = %d).\n", count);
+ }
+ DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
+ }
+ else
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Going to deliver device "
+ "events (count = %d).\n", count);
+ }
+ DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
+ mouse, count);
+ }
+ #else
+ else if (!CheckMotion(xE))
+ return;
+ if (grab)
+ DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
+ else
+ DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
+ mouse, count);
+ #endif
+ if (deactivateGrab)
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Deactivating grab on pointer.\n");
+ }
+ #endif
+ (*mouse->DeactivateGrab)(mouse);
+ #ifdef NX_DEBUG_INPUT
+ }
+ #endif
+}
+
+#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; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ }
+ else
+ {
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
+ FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ /* next call catches the root too, if the screen changed */
+ FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
+ NotifyNonlinearVirtual, FALSE);
+ }
+ /* Notify all the roots */
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
+ if (toWin == PointerRootWin)
+ (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
+ NotifyPointer, TRUE);
+ }
+ else
+ {
+ if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
+ {
+ if (fromWin == PointerRootWin)
+ FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+ TRUE);
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
+ NotifyNonlinearVirtual, TRUE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
+ NotifyPointer, FALSE);
+ }
+ else
+ {
+ if (IsParent(toWin, fromWin))
+ {
+ FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
+ FocusOutEvents(dev, fromWin->parent, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
+ if ((IsParent(toWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(fromWin, sprite.win)) &&
+ (!IsParent(sprite.win, fromWin)))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ else
+ if (IsParent(fromWin, toWin))
+ {
+ if ((IsParent(fromWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(toWin, sprite.win)) &&
+ (!IsParent(sprite.win, toWin)))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
+ (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
+ }
+ else
+ {
+ /* neither fromWin or toWin is child of other */
+ WindowPtr common = CommonAncestor(toWin, fromWin);
+ /* common == NullWindow ==> different screens */
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ if (fromWin->parent != NullWindow)
+ FocusOutEvents(dev, fromWin->parent, common, mode,
+ NotifyNonlinearVirtual, FALSE);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, common, toWin, toWin, mode,
+ NotifyNonlinearVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ }
+ }
+}
+
+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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcGrabPointer: pWin [%p] client [%d].\n", pWin, client -> index);
+ }
+ #endif
+ 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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcGrabPointer: Activating active grab on pointer.\n");
+ }
+ #endif
+ (*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);
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabPointer: client [%d].\n", client -> index);
+ }
+ #endif
+ 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))
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabPointer: Deactivating grab on pointer.\n");
+ }
+ #endif
+ (*device->DeactivateGrab)(device);
+ #ifdef NX_DEBUG_INPUT
+ }
+ else
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabPointer: current time [%lu] request time [%lu] grab time [%lu].\n",
+ currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds);
+ }
+ }
+ #endif
+ 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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "GrabDevice: Activating active grab on keyboard.\n");
+ }
+ #endif
+ (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
+ *status = GrabSuccess;
+ }
+ return Success;
+}
+
+int
+ProcGrabKeyboard(ClientPtr client)
+{
+ xGrabKeyboardReply rep;
+ REQUEST(xGrabKeyboardReq);
+ int result;
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcGrabKeyboard: client [%d].\n", client -> index);
+ }
+ #endif
+ 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);
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabKeyboard: client [%d].\n", client -> index);
+ }
+ #endif
+ 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))
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabKeyboard: Deactivating grab on keyboard.\n");
+ }
+ #endif
+ (*device->DeactivateGrab)(device);
+ #ifdef NX_DEBUG_INPUT
+ }
+ else
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabKeyboard: current time [%lu] request time [%lu] grab time [%lu].\n",
+ currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds);
+ }
+ }
+ #endif
+ 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..c5593adbb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c.NX.original
@@ -0,0 +1,5044 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "Xlib.h"
+#include "misc.h"
+#include "resource.h"
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/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 <X11/extensions/XKBsrv.h>
+extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
+#endif
+
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/security.h>
+#endif
+
+#ifdef XEVIE
+extern WindowPtr *WindowTable;
+extern int xevieFlag;
+extern int xevieClientIndex;
+extern DeviceIntPtr xeviemouse;
+extern DeviceIntPtr xeviekb;
+extern Mask xevieMask;
+extern Mask xevieFilters[128];
+extern int xevieEventSent;
+extern int xevieKBEventSent;
+int xeviegrabState = 0;
+xEvent *xeviexE;
+#endif
+
+#include <X11/extensions/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"
+#include "Args.h"
+
+#ifdef NX_DEBUG_INPUT
+extern int nxagentDebugInput;
+extern int nxagentDebugInputDevices;
+#endif
+
+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 Button<n>MotionMasks are equal
+ * to the corresponding Button<n>Masks 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 NX_DEBUG_INPUT
+ if (grab && nxagentDebugInput && grab->window)
+ {
+ fprintf(stderr, "TryClientEvents: Grab window is [0x%x].\n",
+ (unsigned int)grab->window->drawable.id);
+ if (!SameClient(grab, client))
+ fprintf(stderr, "TryClientEvents: Events are going to be "
+ "discarded.\n");
+ }
+#endif
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ fprintf(stderr, "Event([%d, %d], mask=0x%x), client=%d",
+ pEvents->u.u.type, pEvents->u.u.detail, (unsigned int)mask,
+ client->index);
+#else
+ if (debug_events) ErrorF(
+ "Event([%d, %d], mask=0x%x), client=%d",
+ pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
+#endif
+#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)
+ {
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr,"\nmotionHintWindow == keyButtonPointer.event\n");
+ }
+#else
+ if (debug_events) ErrorF("\n");
+ fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n");
+#endif
+#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);
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ fprintf(stderr, " delivered\n");
+#else
+ if (debug_events) ErrorF( " delivered\n");
+#endif
+#endif
+ return 1;
+ }
+ else
+ {
+#if defined(DEBUG) || defined(NX_DEBUG_INPUT)
+#ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ fprintf(stderr, "\n");
+#else
+ if (debug_events) ErrorF("\n");
+#endif
+#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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "DeliverEventsToWindow: Activating passive grab on pointer.\n");
+ }
+ #endif
+ (*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
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "CheckPassiveGrabsOnWindow: Activating passive grab on %s.\n",
+ device == inputInfo.keyboard ? "keyboard" : "pointer");
+ }
+ #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)
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcessKeyboardEvent: Deactivating grab on keyboard.\n");
+ }
+ #endif
+ (*keybd->DeactivateGrab)(keybd);
+ #ifdef NX_DEBUG_INPUT
+ }
+ #endif
+}
+
+#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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Going to send XEVIE event.\n");
+ }
+ #endif
+ 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
+ #ifdef NX_DEBUG_INPUT
+ if (xE->u.u.detail == 0)
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0"
+ " for ButtonPress.\n");
+ }
+ return;
+ }
+ #else
+ if (xE->u.u.detail == 0)
+ return;
+ #endif
+ if (xE->u.u.detail <= 5)
+ butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
+ filters[MotionNotify] = Motion_Filter(butc);
+ if (!grab)
+ #ifdef NX_DEBUG_INPUT
+ if (CheckDeviceGrabs(mouse, xE, 0, count))
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: CheckDeviceGrabs"
+ " returned True for ButtonPress.\n");
+ }
+ return;
+ }
+ #else
+ if (CheckDeviceGrabs(mouse, xE, 0, count))
+ return;
+ #endif
+ 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
+ #ifdef NX_DEBUG_INPUT
+ if (xE->u.u.detail == 0)
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: WARNING! detail == 0"
+ " for ButtonRelease.\n");
+ }
+ return;
+ }
+ #else
+ if (xE->u.u.detail == 0)
+ return;
+ #endif
+ 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");
+ }
+ }
+ #ifdef NX_DEBUG_INPUT
+ else if (!CheckMotion(xE))
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: CheckMotion returned False"
+ " for MotionNotify.\n");
+ }
+ return;
+ }
+ if (grab)
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Going to deliver grabbed "
+ "events (count = %d).\n", count);
+ }
+ DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
+ }
+ else
+ {
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Going to deliver device "
+ "events (count = %d).\n", count);
+ }
+ DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
+ mouse, count);
+ }
+ #else
+ else if (!CheckMotion(xE))
+ return;
+ if (grab)
+ DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
+ else
+ DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
+ mouse, count);
+ #endif
+ if (deactivateGrab)
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcessPointerEvent: Deactivating grab on pointer.\n");
+ }
+ #endif
+ (*mouse->DeactivateGrab)(mouse);
+ #ifdef NX_DEBUG_INPUT
+ }
+ #endif
+}
+
+#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; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ }
+ else
+ {
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
+ FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ /* next call catches the root too, if the screen changed */
+ FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
+ NotifyNonlinearVirtual, FALSE);
+ }
+ /* Notify all the roots */
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
+ if (toWin == PointerRootWin)
+ (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
+ NotifyPointer, TRUE);
+ }
+ else
+ {
+ if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
+ {
+ if (fromWin == PointerRootWin)
+ FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+ TRUE);
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
+ NotifyNonlinearVirtual, TRUE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
+ NotifyPointer, FALSE);
+ }
+ else
+ {
+ if (IsParent(toWin, fromWin))
+ {
+ FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
+ FocusOutEvents(dev, fromWin->parent, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
+ if ((IsParent(toWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(fromWin, sprite.win)) &&
+ (!IsParent(sprite.win, fromWin)))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ else
+ if (IsParent(fromWin, toWin))
+ {
+ if ((IsParent(fromWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(toWin, sprite.win)) &&
+ (!IsParent(sprite.win, toWin)))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
+ (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
+ }
+ else
+ {
+ /* neither fromWin or toWin is child of other */
+ WindowPtr common = CommonAncestor(toWin, fromWin);
+ /* common == NullWindow ==> different screens */
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ if (fromWin->parent != NullWindow)
+ FocusOutEvents(dev, fromWin->parent, common, mode,
+ NotifyNonlinearVirtual, FALSE);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, common, toWin, toWin, mode,
+ NotifyNonlinearVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ }
+ }
+}
+
+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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcGrabPointer: pWin [%p] client [%d].\n", pWin, client -> index);
+ }
+ #endif
+ 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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcGrabPointer: Activating active grab on pointer.\n");
+ }
+ #endif
+ (*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);
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabPointer: client [%d].\n", client -> index);
+ }
+ #endif
+ 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))
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabPointer: Deactivating grab on pointer.\n");
+ }
+ #endif
+ (*device->DeactivateGrab)(device);
+ #ifdef NX_DEBUG_INPUT
+ }
+ else
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabPointer: current time [%lu] request time [%lu] grab time [%lu].\n",
+ currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds);
+ }
+ }
+ #endif
+ 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;
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "GrabDevice: Activating active grab on keyboard.\n");
+ }
+ #endif
+ (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
+ *status = GrabSuccess;
+ }
+ return Success;
+}
+
+int
+ProcGrabKeyboard(ClientPtr client)
+{
+ xGrabKeyboardReply rep;
+ REQUEST(xGrabKeyboardReq);
+ int result;
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcGrabKeyboard: client [%d].\n", client -> index);
+ }
+ #endif
+ 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);
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabKeyboard: client [%d].\n", client -> index);
+ }
+ #endif
+ 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))
+ #ifdef NX_DEBUG_INPUT
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabKeyboard: Deactivating grab on keyboard.\n");
+ }
+ #endif
+ (*device->DeactivateGrab)(device);
+ #ifdef NX_DEBUG_INPUT
+ }
+ else
+ {
+ if (nxagentDebugInputDevices == 1)
+ {
+ fprintf(stderr, "ProcUngrabKeyboard: current time [%lu] request time [%lu] grab time [%lu].\n",
+ currentTime.milliseconds, time.milliseconds, device->grabTime.milliseconds);
+ }
+ }
+ #endif
+ 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "misc.h"
+#include "resource.h"
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/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 <X11/extensions/XKBsrv.h>
+extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
+#endif
+
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/security.h>
+#endif
+
+#ifdef XEVIE
+extern WindowPtr *WindowTable;
+extern int xevieFlag;
+extern int xevieClientIndex;
+extern DeviceIntPtr xeviemouse;
+extern DeviceIntPtr xeviekb;
+extern Mask xevieMask;
+extern Mask xevieFilters[128];
+extern int xevieEventSent;
+extern int xevieKBEventSent;
+int xeviegrabState = 0;
+xEvent *xeviexE;
+#endif
+
+#include <X11/extensions/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 Button<n>MotionMasks are equal
+ * to the corresponding Button<n>Masks 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; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ }
+ else
+ {
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
+ FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ /* next call catches the root too, if the screen changed */
+ FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
+ NotifyNonlinearVirtual, FALSE);
+ }
+ /* Notify all the roots */
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
+ if (toWin == PointerRootWin)
+ (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
+ NotifyPointer, TRUE);
+ }
+ else
+ {
+ if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
+ {
+ if (fromWin == PointerRootWin)
+ FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+ TRUE);
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
+ else
+#endif
+ for (i=0; i<screenInfo.numScreens; i++)
+ FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
+ NotifyNonlinearVirtual, TRUE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
+ NotifyPointer, FALSE);
+ }
+ else
+ {
+ if (IsParent(toWin, fromWin))
+ {
+ FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
+ FocusOutEvents(dev, fromWin->parent, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
+ if ((IsParent(toWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(fromWin, sprite.win)) &&
+ (!IsParent(sprite.win, fromWin)))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ else
+ if (IsParent(fromWin, toWin))
+ {
+ if ((IsParent(fromWin, sprite.win)) &&
+ (sprite.win != fromWin) &&
+ (!IsParent(toWin, sprite.win)) &&
+ (!IsParent(sprite.win, toWin)))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
+ (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
+ NotifyVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
+ }
+ else
+ {
+ /* neither fromWin or toWin is child of other */
+ WindowPtr common = CommonAncestor(toWin, fromWin);
+ /* common == NullWindow ==> different screens */
+ if (IsParent(fromWin, sprite.win))
+ FocusOutEvents(dev, sprite.win, fromWin, mode,
+ NotifyPointer, FALSE);
+ FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
+ if (fromWin->parent != NullWindow)
+ FocusOutEvents(dev, fromWin->parent, common, mode,
+ NotifyNonlinearVirtual, FALSE);
+ if (toWin->parent != NullWindow)
+ (void)FocusInEvents(dev, common, toWin, toWin, mode,
+ NotifyNonlinearVirtual, FALSE);
+ FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
+ if (IsParent(toWin, sprite.win))
+ (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+ mode, NotifyPointer, FALSE);
+ }
+ }
+ }
+}
+
+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..ead9b9d28
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c
@@ -0,0 +1,508 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/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 <X11/extensions/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(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; i<NumExtensions; i++)
+ {
+ if ((strlen(extensions[i]->name) == 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; i<MAXSCREENS; i++)
+ {
+ register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i];
+
+ while (spentry->num)
+ {
+ 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; i<NumExtensions; i++)
+ {
+#ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ if (client->trustLevel == 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; i<NumExtensions; i++)
+ {
+ int len;
+#ifdef XCSECURITY
+ if (client->trustLevel == 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..ead9b9d28
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXextension.c.NX.original
@@ -0,0 +1,508 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/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 <X11/extensions/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(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; i<NumExtensions; i++)
+ {
+ if ((strlen(extensions[i]->name) == 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; i<MAXSCREENS; i++)
+ {
+ register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i];
+
+ while (spentry->num)
+ {
+ 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; i<NumExtensions; i++)
+ {
+#ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ if (client->trustLevel == 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; i<NumExtensions; i++)
+ {
+ int len;
+#ifdef XCSECURITY
+ if (client->trustLevel == 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/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 <X11/extensions/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(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; i<NumExtensions; i++)
+ {
+ if ((strlen(extensions[i]->name) == 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; i<MAXSCREENS; i++)
+ {
+ register ScreenProcEntry *spentry = &AuxillaryScreenProcs[i];
+
+ while (spentry->num)
+ {
+ 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; i<NumExtensions; i++)
+ {
+#ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ if (client->trustLevel == 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; i<NumExtensions; i++)
+ {
+ int len;
+#ifdef XCSECURITY
+ if (client->trustLevel == 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..51c547984
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c
@@ -0,0 +1,575 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include "glxserver.h"
+#include <windowstr.h>
+#include <propertyst.h>
+#include <os.h>
+#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..51c547984
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglxext.c.NX.original
@@ -0,0 +1,575 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include "glxserver.h"
+#include <windowstr.h>
+#include <propertyst.h>
+#include <os.h>
+#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 <dix-config.h>
+#endif
+
+#include "glxserver.h"
+#include <windowstr.h>
+#include <propertyst.h>
+#include <os.h>
+#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..cd65fdc0e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c
@@ -0,0 +1,581 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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
+
+#else
+
+#include "picturestr.h"
+#include "glyphstr.h"
+
+#endif
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif !defined(UINT32_MAX)
+#define UINT32_MAX 0xffffffffU
+#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_t padded_width;
+
+ padded_width = PixmapBytePad (gi->width, glyphDepths[fdepth]);
+ if (gi->height && padded_width > (UINT32_MAX - sizeof(GlyphRec))/gi->height)
+ return 0;
+ size = gi->height * padded_width;
+ 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..cd65fdc0e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.NX.original
@@ -0,0 +1,581 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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
+
+#else
+
+#include "picturestr.h"
+#include "glyphstr.h"
+
+#endif
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif !defined(UINT32_MAX)
+#define UINT32_MAX 0xffffffffU
+#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_t padded_width;
+
+ padded_width = PixmapBytePad (gi->width, glyphDepths[fdepth]);
+ if (gi->height && padded_width > (UINT32_MAX - sizeof(GlyphRec))/gi->height)
+ return 0;
+ size = gi->height * padded_width;
+ 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..9f4d1c87b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyph.c.X.original
@@ -0,0 +1,488 @@
+/*
+ * $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 <dix-config.h>
+#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"
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif !defined(UINT32_MAX)
+#define UINT32_MAX 0xffffffffU
+#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;
+ 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_t padded_width;
+
+ padded_width = PixmapBytePad (gi->width, glyphDepths[fdepth]);
+ if (gi->height && padded_width > (UINT32_MAX - sizeof(GlyphRec))/gi->height)
+ return 0;
+ size = gi->height * padded_width;
+ 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..7a1d813b3
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c
@@ -0,0 +1,241 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include "misc.h"
+#include <X11/fonts/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(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..7a1d813b3
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphcurs.c.NX.original
@@ -0,0 +1,241 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include "misc.h"
+#include <X11/fonts/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(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 <dix-config.h>
+#endif
+
+#include "misc.h"
+#include <X11/fonts/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(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..fa6b5fb02
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h
@@ -0,0 +1,174 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <X11/extensions/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;
+ 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..fa6b5fb02
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXglyphstr.h.NX.original
@@ -0,0 +1,174 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <X11/extensions/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;
+ 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 <X11/extensions/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;
+ 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..3fc73cf3b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c
@@ -0,0 +1,979 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include <X11/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 <X11/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_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..3fc73cf3b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiexpose.c.NX.original
@@ -0,0 +1,979 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include <X11/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 <X11/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_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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include <X11/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 <X11/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_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..5f32334ae
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c
@@ -0,0 +1,318 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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..5f32334ae
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiglyph.c.NX.original
@@ -0,0 +1,318 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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 <dix-config.h>
+#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..f418654b4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c
@@ -0,0 +1,233 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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..f418654b4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmitrap.c.NX.original
@@ -0,0 +1,233 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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 <dix-config.h>
+#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..190294979
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c
@@ -0,0 +1,1222 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#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, &reg, &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, &reg, &reg, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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..190294979
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXmiwindow.c.NX.original
@@ -0,0 +1,1222 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#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, &reg, &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, &reg, &reg, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#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, &reg, &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, &reg, &reg, &pWin->clipList);
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
+ else if (pWin->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
+ REGION_UNINIT(pScreen, &reg);
+ 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..d9054b4b6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c
@@ -0,0 +1,2270 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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"
+#include "Render.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;
+ }
+
+ nxagentPicturePriv(pPicture) -> picture = 0;
+
+ 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;
+
+ extern int nxagentPicturePrivateIndex;
+
+ unsigned int totalPictureSize;
+
+ DevUnion *ppriv;
+
+ char *privPictureRecAddr;
+
+ int i;
+
+ /*
+ * Compute size of entire PictureRect, plus privates.
+ */
+
+ totalPictureSize = sizeof(PictureRec) +
+ picturePrivateCount * sizeof(DevUnion) +
+ sizeof(nxagentPrivPictureRec);
+
+ pPicture = (PicturePtr) xalloc(totalPictureSize);
+
+ if (pPicture != NULL)
+ {
+ ppriv = (DevUnion *) (pPicture + 1);
+
+ for (i = 0; i < picturePrivateCount; ++i)
+ {
+ /*
+ * Other privates are inaccessible.
+ */
+
+ ppriv[i].ptr = NULL;
+ }
+
+ privPictureRecAddr = (char *) &ppriv[picturePrivateCount];
+
+ ppriv[nxagentPicturePrivateIndex].ptr = (pointer) privPictureRecAddr;
+
+ pPicture -> devPrivates = ppriv;
+
+ nxagentPicturePriv(pPicture) -> picture = 0;
+ }
+
+ 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)
+ {
+#ifdef NXAGENT_SERVER
+ nxagentDestroyPicture(pPicture);
+#endif
+
+ 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..d9054b4b6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicture.c.NX.original
@@ -0,0 +1,2270 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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"
+#include "Render.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;
+ }
+
+ nxagentPicturePriv(pPicture) -> picture = 0;
+
+ 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;
+
+ extern int nxagentPicturePrivateIndex;
+
+ unsigned int totalPictureSize;
+
+ DevUnion *ppriv;
+
+ char *privPictureRecAddr;
+
+ int i;
+
+ /*
+ * Compute size of entire PictureRect, plus privates.
+ */
+
+ totalPictureSize = sizeof(PictureRec) +
+ picturePrivateCount * sizeof(DevUnion) +
+ sizeof(nxagentPrivPictureRec);
+
+ pPicture = (PicturePtr) xalloc(totalPictureSize);
+
+ if (pPicture != NULL)
+ {
+ ppriv = (DevUnion *) (pPicture + 1);
+
+ for (i = 0; i < picturePrivateCount; ++i)
+ {
+ /*
+ * Other privates are inaccessible.
+ */
+
+ ppriv[i].ptr = NULL;
+ }
+
+ privPictureRecAddr = (char *) &ppriv[picturePrivateCount];
+
+ ppriv[nxagentPicturePrivateIndex].ptr = (pointer) privPictureRecAddr;
+
+ pPicture -> devPrivates = ppriv;
+
+ nxagentPicturePriv(pPicture) -> picture = 0;
+ }
+
+ 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)
+ {
+#ifdef NXAGENT_SERVER
+ nxagentDestroyPicture(pPicture);
+#endif
+
+ 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 <dix-config.h>
+#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..0d1a8e1d8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h
@@ -0,0 +1,678 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..0d1a8e1d8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXpicturestr.h.NX.original
@@ -0,0 +1,678 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..cd1ec6ddd
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c
@@ -0,0 +1,992 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include "windowstr.h"
+#include "propertyst.h"
+#include "dixstruct.h"
+#include "../../dix/dispatch.h"
+#include "swaprep.h"
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/security.h>
+#endif
+#ifdef LBX
+#include "lbxserve.h"
+#include "lbxtags.h"
+#endif
+
+#include "Options.h"
+#include "Rootless.h"
+#include "Client.h"
+#include "Windows.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
+
+extern Atom clientCutProperty;
+
+#ifdef NXAGENT_SERVER
+typedef struct
+{
+ CARD32 state;
+ Window icon;
+}
+nxagentWMStateRec;
+#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);
+
+ #ifdef NX_DEBUG_INPUT
+ nxagentGuessDumpInputInfo(client, stuff->property, (char *) &stuff[1]);
+ #endif
+
+ 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;
+ int copySize;
+
+ sizeInBytes = format>>3;
+ totalSize = len * sizeInBytes;
+
+ copySize = nxagentOption(CopyBufferSize);
+
+ if (copySize != COPY_UNLIMITED && property == clientCutProperty)
+ {
+ if (totalSize > copySize)
+ {
+ totalSize = copySize;
+ totalSize = totalSize - (totalSize % sizeInBytes);
+ len = totalSize / 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)
+{
+ #ifdef NXAGENT_SERVER
+ nxagentWMStateRec wmState;
+ nxagentWMStateRec *wmsP = &wmState;
+ #endif
+
+ 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;
+
+ #ifdef NXAGENT_SERVER
+
+ /*
+ * Creating a reply for WM_STATE property if it doesn't exist.
+ * This is intended to allow drag & drop work in JAva 1.6 when
+ * the agent is connected to NXWin in multiwindow mode.
+ */
+
+ if (nxagentOption(Rootless) &&
+ nxagentWindowTopLevel(pWin) &&
+ (!pProp) &&
+ strcmp(NameForAtom(stuff->property), "WM_STATE") == 0)
+ {
+ wmState.state = 1;
+ wmState.icon = None;
+
+ if (ChangeWindowProperty(pWin, stuff->property, stuff->property, 32, 0, 2, &wmState, 1) == Success)
+ {
+ nxagentExportProperty(pWin, stuff->property, stuff->property, 32, 0, 2, &wmState);
+ }
+
+ n = 8;
+ ind = stuff->longOffset << 2;
+
+ if (n < ind)
+ {
+ client->errorValue = stuff->longOffset;
+ return BadValue;
+ }
+
+ len = min(n - ind, 4 * stuff->longLength);
+
+ reply.bytesAfter = n - (ind + len);
+ reply.length = (len + 3) >> 2;
+
+ reply.format = 32;
+ reply.nItems = len / 4;
+ reply.propertyType = stuff->property;
+
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+
+ if (len)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write;
+
+ WriteSwappedDataToClient(client, len, (char *)wmsP + ind);
+ }
+
+ return(client->noClientException);
+ }
+ #endif
+
+ 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..cd1ec6ddd
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXproperty.c.NX.original
@@ -0,0 +1,992 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include "windowstr.h"
+#include "propertyst.h"
+#include "dixstruct.h"
+#include "../../dix/dispatch.h"
+#include "swaprep.h"
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/security.h>
+#endif
+#ifdef LBX
+#include "lbxserve.h"
+#include "lbxtags.h"
+#endif
+
+#include "Options.h"
+#include "Rootless.h"
+#include "Client.h"
+#include "Windows.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
+
+extern Atom clientCutProperty;
+
+#ifdef NXAGENT_SERVER
+typedef struct
+{
+ CARD32 state;
+ Window icon;
+}
+nxagentWMStateRec;
+#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);
+
+ #ifdef NX_DEBUG_INPUT
+ nxagentGuessDumpInputInfo(client, stuff->property, (char *) &stuff[1]);
+ #endif
+
+ 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;
+ int copySize;
+
+ sizeInBytes = format>>3;
+ totalSize = len * sizeInBytes;
+
+ copySize = nxagentOption(CopyBufferSize);
+
+ if (copySize != COPY_UNLIMITED && property == clientCutProperty)
+ {
+ if (totalSize > copySize)
+ {
+ totalSize = copySize;
+ totalSize = totalSize - (totalSize % sizeInBytes);
+ len = totalSize / 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)
+{
+ #ifdef NXAGENT_SERVER
+ nxagentWMStateRec wmState;
+ nxagentWMStateRec *wmsP = &wmState;
+ #endif
+
+ 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;
+
+ #ifdef NXAGENT_SERVER
+
+ /*
+ * Creating a reply for WM_STATE property if it doesn't exist.
+ * This is intended to allow drag & drop work in JAva 1.6 when
+ * the agent is connected to NXWin in multiwindow mode.
+ */
+
+ if (nxagentOption(Rootless) &&
+ nxagentWindowTopLevel(pWin) &&
+ (!pProp) &&
+ strcmp(NameForAtom(stuff->property), "WM_STATE") == 0)
+ {
+ wmState.state = 1;
+ wmState.icon = None;
+
+ if (ChangeWindowProperty(pWin, stuff->property, stuff->property, 32, 0, 2, &wmState, 1) == Success)
+ {
+ nxagentExportProperty(pWin, stuff->property, stuff->property, 32, 0, 2, &wmState);
+ }
+
+ n = 8;
+ ind = stuff->longOffset << 2;
+
+ if (n < ind)
+ {
+ client->errorValue = stuff->longOffset;
+ return BadValue;
+ }
+
+ len = min(n - ind, 4 * stuff->longLength);
+
+ reply.bytesAfter = n - (ind + len);
+ reply.length = (len + 3) >> 2;
+
+ reply.format = 32;
+ reply.nItems = len / 4;
+ reply.propertyType = stuff->property;
+
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+
+ if (len)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write;
+
+ WriteSwappedDataToClient(client, len, (char *)wmsP + ind);
+ }
+
+ return(client->noClientException);
+ }
+ #endif
+
+ 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+#include "windowstr.h"
+#include "propertyst.h"
+#include "dixstruct.h"
+#include "dispatch.h"
+#include "swaprep.h"
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/security.h>
+#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/NXrender.c b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c
new file mode 100644
index 000000000..89e790135
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c
@@ -0,0 +1,3861 @@
+/* $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, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/render.h>
+#include <X11/extensions/renderproto.h>
+#include <X11/Xfuncproto.h>
+#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 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);
+
+void nxagentRenderCreateSolidFill(PicturePtr pPicture, xRenderColor *color);
+
+void nxagentRenderCreateLinearGradient(PicturePtr pPicture, xPointFixed *p1,
+ xPointFixed *p2, int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+
+void nxagentRenderCreateRadialGradient(PicturePtr pPicture, xPointFixed *inner,
+ xPointFixed *outer,
+ xFixed innerRadius,
+ xFixed outerRadius,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+
+void nxagentRenderCreateConicalGradient(PicturePtr pPicture,
+ xPointFixed *center,
+ xFixed angle, int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+
+
+/*
+ * 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);
+
+ 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);
+/*
+FIXME: Imported change from newest version of Xorg. Changed pSrc to pDst.
+
+ if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
+ (pMask && pMask->pDrawable && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen))
+ return BadMatch;
+*/
+ if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
+ (pMask && pMask->pDrawable && pDst->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 (height && width > UINT32_MAX/(height*sizeof(CARD32)))
+ return BadAlloc;
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateSolidFill(pPicture, &stuff -> color);
+
+ /* AGENT SERVER */
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateLinearGradient(pPicture, &stuff->p1, &stuff->p2,
+ stuff->nStops, stops, colors);
+
+ /* AGENT SERVER */
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateRadialGradient(pPicture, &stuff->inner, &stuff->outer,
+ stuff->inner_radius,
+ stuff->outer_radius,
+ stuff->nStops, stops, colors);
+
+ /* AGENT SERVER */
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateConicalGradient(pPicture, &stuff->center,
+ stuff->angle, stuff->nStops, stops,
+ colors);
+
+ /* AGENT SERVER */
+ 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 num)
+{
+ int i, n;
+ CARD32 *stops;
+ CARD16 *colors;
+ stops = (CARD32 *)(stuff);
+ for (i = 0; i < num; ++i) {
+ swapl(stops, n);
+ ++stops;
+ }
+ colors = (CARD16 *)(stops);
+ for (i = 0; i < 4*num; ++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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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..89e790135
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.NX.original
@@ -0,0 +1,3861 @@
+/* $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, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/render.h>
+#include <X11/extensions/renderproto.h>
+#include <X11/Xfuncproto.h>
+#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 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);
+
+void nxagentRenderCreateSolidFill(PicturePtr pPicture, xRenderColor *color);
+
+void nxagentRenderCreateLinearGradient(PicturePtr pPicture, xPointFixed *p1,
+ xPointFixed *p2, int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+
+void nxagentRenderCreateRadialGradient(PicturePtr pPicture, xPointFixed *inner,
+ xPointFixed *outer,
+ xFixed innerRadius,
+ xFixed outerRadius,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+
+void nxagentRenderCreateConicalGradient(PicturePtr pPicture,
+ xPointFixed *center,
+ xFixed angle, int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+
+
+/*
+ * 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);
+
+ 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);
+/*
+FIXME: Imported change from newest version of Xorg. Changed pSrc to pDst.
+
+ if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
+ (pMask && pMask->pDrawable && pSrc->pDrawable->pScreen != pMask->pDrawable->pScreen))
+ return BadMatch;
+*/
+ if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
+ (pMask && pMask->pDrawable && pDst->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 (height && width > UINT32_MAX/(height*sizeof(CARD32)))
+ return BadAlloc;
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateSolidFill(pPicture, &stuff -> color);
+
+ /* AGENT SERVER */
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateLinearGradient(pPicture, &stuff->p1, &stuff->p2,
+ stuff->nStops, stops, colors);
+
+ /* AGENT SERVER */
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateRadialGradient(pPicture, &stuff->inner, &stuff->outer,
+ stuff->inner_radius,
+ stuff->outer_radius,
+ stuff->nStops, stops, colors);
+
+ /* AGENT SERVER */
+ 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;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateConicalGradient(pPicture, &stuff->center,
+ stuff->angle, stuff->nStops, stops,
+ colors);
+
+ /* AGENT SERVER */
+ 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 num)
+{
+ int i, n;
+ CARD32 *stops;
+ CARD16 *colors;
+ stops = (CARD32 *)(stuff);
+ for (i = 0; i < num; ++i) {
+ swapl(stops, n);
+ ++stops;
+ }
+ colors = (CARD16 *)(stops);
+ for (i = 0; i < 4*num; ++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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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..d25d49756
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXrender.c.X.original
@@ -0,0 +1,3316 @@
+/* $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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/render.h>
+#include <X11/extensions/renderproto.h>
+#include "picturestr.h"
+#include "glyphstr.h"
+#include <X11/Xfuncproto.h>
+#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 (height && width > UINT32_MAX/(height*sizeof(CARD32)))
+ return BadAlloc;
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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 num)
+{
+ int i, n;
+ CARD32 *stops;
+ CARD16 *colors;
+ stops = (CARD32 *)(stuff);
+ for (i = 0; i < num; ++i) {
+ swapl(stops, n);
+ ++stops;
+ }
+ colors = (CARD16 *)(stops);
+ for (i = 0; i < 4*num; ++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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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 (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ 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..d1c8325f2
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c
@@ -0,0 +1,1250 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/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 <assert.h>
+
+#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
+
+#ifdef NXAGENT_SERVER
+static int nxagentResChangedFlag = 0;
+#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<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NullResource;
+ }
+ return TRUE;
+}
+
+
+static int
+Hash(int client, register XID id)
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>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++;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ 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;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ 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;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ 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;
+
+ /*
+ * FIXME:
+ * It is not safe to let a function change the resource
+ * table we are reading!
+ */
+
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 0;
+ #endif
+ (*func)(this->value, this->id, cdata);
+
+ /*
+ * Avoid that a call to RebuildTable() could invalidate the
+ * pointer. This is safe enough, because in RebuildTable()
+ * the new pointer is allocated just before the old one is
+ * freed, so it can't point to the same address.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*resptr != resources)
+ goto RestartLoop;
+ #endif
+
+ /*
+ * It's not enough to check if the number of elements has
+ * changed, beacause it could happen that the number of
+ * resources that have been added matches the number of
+ * the freed ones.
+ * 'nxagentResChangedFlag' is set if a resource has been
+ * added or freed.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*eltptr != elements || nxagentResChangedFlag)
+ #else
+ if (*eltptr != elements)
+ #endif
+ 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;
+
+ /*
+ * FIXME:
+ * It is not safe to let a function change the resource
+ * table we are reading!
+ */
+
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 0;
+ #endif
+ (*func)(this->value, this->id, this->type, cdata);
+
+ /*
+ * Avoid that a call to RebuildTable() could invalidate the
+ * pointer. This is safe enough, because in RebuildTable()
+ * the new pointer is allocated just before the old one is
+ * freed, so it can't point to the same address.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*resptr != resources)
+ goto RestartLoop;
+ #endif
+
+ /*
+ * It's not enough to check if the number of elements has
+ * changed, beacause it could happen that the number of
+ * resources that have been added matches the number of
+ * the freed ones.
+ * 'nxagentResChangedFlag' is set if a resource has been
+ * added or freed.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*eltptr != elements || nxagentResChangedFlag)
+ #else
+ if (*eltptr != elements)
+ #endif
+ 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..d1c8325f2
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.NX.original
@@ -0,0 +1,1250 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/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 <assert.h>
+
+#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
+
+#ifdef NXAGENT_SERVER
+static int nxagentResChangedFlag = 0;
+#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<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NullResource;
+ }
+ return TRUE;
+}
+
+
+static int
+Hash(int client, register XID id)
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>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++;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ 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;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ 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;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ 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;
+
+ /*
+ * FIXME:
+ * It is not safe to let a function change the resource
+ * table we are reading!
+ */
+
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 0;
+ #endif
+ (*func)(this->value, this->id, cdata);
+
+ /*
+ * Avoid that a call to RebuildTable() could invalidate the
+ * pointer. This is safe enough, because in RebuildTable()
+ * the new pointer is allocated just before the old one is
+ * freed, so it can't point to the same address.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*resptr != resources)
+ goto RestartLoop;
+ #endif
+
+ /*
+ * It's not enough to check if the number of elements has
+ * changed, beacause it could happen that the number of
+ * resources that have been added matches the number of
+ * the freed ones.
+ * 'nxagentResChangedFlag' is set if a resource has been
+ * added or freed.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*eltptr != elements || nxagentResChangedFlag)
+ #else
+ if (*eltptr != elements)
+ #endif
+ 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;
+
+ /*
+ * FIXME:
+ * It is not safe to let a function change the resource
+ * table we are reading!
+ */
+
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 0;
+ #endif
+ (*func)(this->value, this->id, this->type, cdata);
+
+ /*
+ * Avoid that a call to RebuildTable() could invalidate the
+ * pointer. This is safe enough, because in RebuildTable()
+ * the new pointer is allocated just before the old one is
+ * freed, so it can't point to the same address.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*resptr != resources)
+ goto RestartLoop;
+ #endif
+
+ /*
+ * It's not enough to check if the number of elements has
+ * changed, beacause it could happen that the number of
+ * resources that have been added matches the number of
+ * the freed ones.
+ * 'nxagentResChangedFlag' is set if a resource has been
+ * added or freed.
+ */
+
+ #ifdef NXAGENT_SERVER
+ if (*eltptr != elements || nxagentResChangedFlag)
+ #else
+ if (*eltptr != elements)
+ #endif
+ 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 <dix-config.h>
+#endif
+
+#include <X11/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 <assert.h>
+
+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<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NullResource;
+ }
+ return TRUE;
+}
+
+
+static int
+Hash(int client, register XID id)
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>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..eaaa92041
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c
@@ -0,0 +1,1498 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#ifndef Lynx
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#else
+#include <ipc.h>
+#include <shm.h>
+#endif
+#include <unistd.h>
+#include <sys/stat.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/shmstr.h>
+#include <X11/Xfuncproto.h>
+#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 <sys/signal.h>
+
+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);
+ unsigned int width, height, depth;
+ unsigned long size;
+ 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);
+
+ width = stuff->width;
+ height = stuff->height;
+ depth = stuff->depth;
+ if (!width || !height || !depth)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (width > 32767 || height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1)
+ {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+
+CreatePmap:
+ size = PixmapBytePad(width, depth) * height;
+ if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
+ if (size < width * height)
+ return BadAlloc;
+ /* thankfully, offset is unsigned */
+ if (stuff->offset + size < size)
+ return BadAlloc;
+ }
+
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, size, 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;
+ }
+
+ /*
+ * There's a potential integer overflow in this check:
+ * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
+ * client);
+ * the version below ought to avoid it
+ */
+ if (stuff->totalHeight != 0 &&
+ length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
+ client->errorValue = stuff->totalWidth;
+ return BadValue;
+ }
+ 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);
+ unsigned int width, height, depth;
+ unsigned long size;
+
+ 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);
+
+ width = stuff->width;
+ height = stuff->height;
+ depth = stuff->depth;
+ if (!width || !height || !depth)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (width > 32767 || height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1)
+ {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+
+CreatePmap:
+ size = PixmapBytePad(width, depth) * height;
+ if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
+ if (size < width * height)
+ return BadAlloc;
+ /* thankfully, offset is unsigned */
+ if (stuff->offset + size < size)
+ return BadAlloc;
+ }
+
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, size, 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..eaaa92041
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.NX.original
@@ -0,0 +1,1498 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#ifndef Lynx
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#else
+#include <ipc.h>
+#include <shm.h>
+#endif
+#include <unistd.h>
+#include <sys/stat.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/shmstr.h>
+#include <X11/Xfuncproto.h>
+#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 <sys/signal.h>
+
+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);
+ unsigned int width, height, depth;
+ unsigned long size;
+ 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);
+
+ width = stuff->width;
+ height = stuff->height;
+ depth = stuff->depth;
+ if (!width || !height || !depth)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (width > 32767 || height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1)
+ {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+
+CreatePmap:
+ size = PixmapBytePad(width, depth) * height;
+ if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
+ if (size < width * height)
+ return BadAlloc;
+ /* thankfully, offset is unsigned */
+ if (stuff->offset + size < size)
+ return BadAlloc;
+ }
+
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, size, 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;
+ }
+
+ /*
+ * There's a potential integer overflow in this check:
+ * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
+ * client);
+ * the version below ought to avoid it
+ */
+ if (stuff->totalHeight != 0 &&
+ length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
+ client->errorValue = stuff->totalWidth;
+ return BadValue;
+ }
+ 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);
+ unsigned int width, height, depth;
+ unsigned long size;
+
+ 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);
+
+ width = stuff->width;
+ height = stuff->height;
+ depth = stuff->depth;
+ if (!width || !height || !depth)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (width > 32767 || height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1)
+ {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+
+CreatePmap:
+ size = PixmapBytePad(width, depth) * height;
+ if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
+ if (size < width * height)
+ return BadAlloc;
+ /* thankfully, offset is unsigned */
+ if (stuff->offset + size < size)
+ return BadAlloc;
+ }
+
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, size, 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..f25bb9b5d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXshm.c.X.original
@@ -0,0 +1,1310 @@
+/* $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 <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#ifndef Lynx
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#else
+#include <ipc.h>
+#include <shm.h>
+#endif
+#include <unistd.h>
+#include <sys/stat.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/shmstr.h>
+#include <X11/Xfuncproto.h>
+#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 <sys/signal.h>
+
+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);
+ unsigned int width, height, depth;
+ unsigned long size;
+ 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);
+
+ width = stuff->width;
+ height = stuff->height;
+ depth = stuff->depth;
+ if (!width || !height || !depth)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (width > 32767 || height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1)
+ {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+
+CreatePmap:
+ size = PixmapBytePad(width, depth) * height;
+ if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
+ if (size < width * height)
+ return BadAlloc;
+ /* thankfully, offset is unsigned */
+ if (stuff->offset + size < size)
+ return BadAlloc;
+ }
+
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, size, 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;
+ }
+
+ /*
+ * There's a potential integer overflow in this check:
+ * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
+ * client);
+ * the version below ought to avoid it
+ */
+ if (stuff->totalHeight != 0 &&
+ length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
+ client->errorValue = stuff->totalWidth;
+ return BadValue;
+ }
+ 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);
+ unsigned int width, height, depth;
+ unsigned long size;
+
+ 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);
+
+ width = stuff->width;
+ height = stuff->height;
+ depth = stuff->depth;
+ if (!width || !height || !depth)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (width > 32767 || height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1)
+ {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+
+CreatePmap:
+ size = PixmapBytePad(width, depth) * height;
+ if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
+ if (size < width * height)
+ return BadAlloc;
+ /* thankfully, offset is unsigned */
+ if (stuff->offset + size < size)
+ return BadAlloc;
+ }
+
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, size, 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..76e86fd2a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c
@@ -0,0 +1,4167 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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 <X11/extensions/Xagsrv.h>
+#endif
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/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"
+
+extern Bool nxagentWMIsRunning;
+extern Bool nxagentScreenTrap;
+
+/******
+ * 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))
+
+
+/*
+ * 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; i<indent; i++) ErrorF( " ");
+ ErrorF( "%x\n", p1->drawable.id);
+ miPrintRegion(&p1->clipList);
+ PrintChildren(p2, indent+4);
+ p1 = p1->nextSib;
+ }
+}
+
+PrintWindowTree()
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i=0; i<screenInfo.numScreens; i++)
+ {
+ ErrorF( "WINDOW %d\n", i);
+ pWin = WindowTable[i];
+ miPrintRegion(&pWin->clipList);
+ 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);
+}
+
+#endif /* 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);
+
+#ifdef NXAGENT_SERVER
+ nxagentRootTileWindow = pWin;
+#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; j<client->numSaved; 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; j<BitmapBytePad(32)*16; j++)
+ srcbits[j] = mskbits[j] = 0x0;
+ cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
+ if (cursor)
+ {
+ cursorID = FakeClientID(0);
+ if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
+ {
+ attributes[attri] = cursorID;
+ mask |= CWCursor;
+ }
+ else
+ cursor = 0;
+ }
+ else
+ {
+ xfree (srcbits);
+ xfree (mskbits);
+ }
+ }
+
+ pWin = savedScreenInfo[i].pWindow =
+ CreateWindow(savedScreenInfo[i].wid,
+ WindowTable[i],
+ -RANDOM_WIDTH, -RANDOM_WIDTH,
+ (unsigned short)screenInfo.screens[i]->width + 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..76e86fd2a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXwindow.c.NX.original
@@ -0,0 +1,4167 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#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 <X11/extensions/Xagsrv.h>
+#endif
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/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"
+
+extern Bool nxagentWMIsRunning;
+extern Bool nxagentScreenTrap;
+
+/******
+ * 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))
+
+
+/*
+ * 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; i<indent; i++) ErrorF( " ");
+ ErrorF( "%x\n", p1->drawable.id);
+ miPrintRegion(&p1->clipList);
+ PrintChildren(p2, indent+4);
+ p1 = p1->nextSib;
+ }
+}
+
+PrintWindowTree()
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i=0; i<screenInfo.numScreens; i++)
+ {
+ ErrorF( "WINDOW %d\n", i);
+ pWin = WindowTable[i];
+ miPrintRegion(&pWin->clipList);
+ 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);
+}
+
+#endif /* 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);
+
+#ifdef NXAGENT_SERVER
+ nxagentRootTileWindow = pWin;
+#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; j<client->numSaved; 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; j<BitmapBytePad(32)*16; j++)
+ srcbits[j] = mskbits[j] = 0x0;
+ cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
+ if (cursor)
+ {
+ cursorID = FakeClientID(0);
+ if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
+ {
+ attributes[attri] = cursorID;
+ mask |= CWCursor;
+ }
+ else
+ cursor = 0;
+ }
+ else
+ {
+ xfree (srcbits);
+ xfree (mskbits);
+ }
+ }
+
+ pWin = savedScreenInfo[i].pWindow =
+ CreateWindow(savedScreenInfo[i].wid,
+ WindowTable[i],
+ -RANDOM_WIDTH, -RANDOM_WIDTH,
+ (unsigned short)screenInfo.screens[i]->width + 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 <dix-config.h>
+#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 <X11/extensions/Xagsrv.h>
+#endif
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <X11/extensions/security.h>
+#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; i<indent; i++) ErrorF( " ");
+ ErrorF( "%x\n", p1->drawable.id);
+ miPrintRegion(&p1->clipList);
+ PrintChildren(p2, indent+4);
+ p1 = p1->nextSib;
+ }
+}
+
+PrintWindowTree()
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i=0; i<screenInfo.numScreens; i++)
+ {
+ ErrorF( "WINDOW %d\n", i);
+ pWin = WindowTable[i];
+ miPrintRegion(&pWin->clipList);
+ 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; j<client->numSaved; 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; j<BitmapBytePad(32)*16; j++)
+ srcbits[j] = mskbits[j] = 0x0;
+ cursor = AllocCursor(srcbits, mskbits, &cm, 0, 0, 0, 0, 0, 0);
+ if (cursor)
+ {
+ cursorID = FakeClientID(0);
+ if (AddResource (cursorID, RT_CURSOR, (pointer) cursor))
+ {
+ attributes[attri] = cursorID;
+ mask |= CWCursor;
+ }
+ else
+ cursor = 0;
+ }
+ else
+ {
+ xfree (srcbits);
+ xfree (mskbits);
+ }
+ }
+
+ pWin = savedScreenInfo[i].pWindow =
+ CreateWindow(savedScreenInfo[i].wid,
+ WindowTable[i],
+ -RANDOM_WIDTH, -RANDOM_WIDTH,
+ (unsigned short)screenInfo.screens[i]->width + 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..f6dad312a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c
@@ -0,0 +1,2286 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/Xv.h>
+#include <X11/extensions/Xvproto.h>
+#include "xvdix.h"
+#ifdef MITSHM
+#define _XSHM_SERVER_
+#include <X11/extensions/shmstr.h>
+#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..f6dad312a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X/NXxvdisp.c.NX.original
@@ -0,0 +1,2286 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/Xv.h>
+#include <X11/extensions/Xvproto.h>
+#include "xvdix.h"
+#ifdef MITSHM
+#define _XSHM_SERVER_
+#include <X11/extensions/shmstr.h>
+#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 <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/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 <X11/extensions/Xv.h>
+#include <X11/extensions/Xvproto.h>
+#include "xvdix.h"
+#ifdef MITSHM
+#define _XSHM_SERVER_
+#include <X11/extensions/shmstr.h>
+#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..dd8be6cb3
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm
@@ -0,0 +1,41 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..854e0a611
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm
@@ -0,0 +1,48 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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..9ec7e6bc8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/os2Stub.c
@@ -0,0 +1,402 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+/*
+ * (c) Copyright 1996 by Sebastien Marineau
+ * <marineau@genie.uottawa.ca>
+ *
+ * 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 <stdio.h>
+#include <sys/select.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSNPIPES
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#undef BOOL
+#undef BYTE
+#include <os2.h>
+
+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..ef7cd661a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/screensaver
@@ -0,0 +1,703 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 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 Medialogic S.p.A. */
+/* */
+/* 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};
diff --git a/nx-X11/programs/nxauth/CHANGELOG b/nx-X11/programs/nxauth/CHANGELOG
new file mode 100644
index 000000000..9faf9eba2
--- /dev/null
+++ b/nx-X11/programs/nxauth/CHANGELOG
@@ -0,0 +1,108 @@
+ChangeLog:
+
+nxauth-3.5.0-1
+
+- Opened the 3.5.0 branch based on nxauth-3.4.0-3.
+
+- Updated copyright to year 2011.
+
+nxauth-3.4.0-3
+
+- Updated the launchd socket detection to support OSX versions relea-
+ sed so far.
+
+nxauth-3.4.0-2
+
+- Updated copyright to year 2010.
+
+nxauth-3.4.0-1
+
+- Opened the 3.4.0 branch based on nxauth-3.3.0-1.
+
+- Updated copyright to year 2009.
+
+nxauth-3.3.0-1
+
+- Opened the 3.3.0 branch based on nxauth-3.2.0-1.
+
+nxauth-3.2.0-1
+
+- Opened the 3.2.0 branch based on nxauth-3.1.0-2.
+
+nxauth-3.1.0-2
+
+- Added support for launchd socket.
+
+nxauth-3.1.0-1
+
+- Opened the 3.1.0 branch based on nxauth-3.0.0-6.
+
+nxauth-3.0.0-6
+
+- Updated the NoMachine copyright notice.
+
+nxauth-3.0.0-5
+
+- Changed the copyright attribution from Medialogic to NoMachine.
+
+nxauth-3.0.0-4
+
+- Changed the LICENSE file to state that the software is only made
+ available under the version 2 of the GPL.
+
+- Added file COPYING.
+
+nxauth-3.0.0-3
+
+- Updated copyright notices to year 2007.
+
+nxauth-3.0.0-2
+
+- Imported changes up to nxauth-2.1.0-1.
+
+- Ignoring lock on '.Xauthority' file.
+
+- Using '__CYGWIN__' definition in process.c. 'WIN32' is not defined
+ during compilation under nx-X11 and wrong code block is used to
+ rename xauth temporary file.
+
+nxauth-3.0.0-1
+
+- Opened the 3.0.0 branch based on nxauth-2.0.0-2.
+
+nxauth-2.0.0-2
+
+- Updated the NoMachine copyright notices.
+
+nxauth-2.0.0-1
+
+- Opened the 2.0.0 branch based on the 1.6.0-1.
+
+nxauth-1.6.0-1
+
+- Opened the 1.6.0 branch based on nxauth-1.5.0-1.
+
+nxauth-1.5.0-1
+
+- Opened the 1.5.0 branch.
+
+nxauth-1.4.1-1
+
+- Opened the 1.4.1 branch.
+
+nxauth-1.4.0-2
+
+- Removed debug message 'host name is'.
+
+nxauth-1.4.0-1
+
+- Opened the 1.4.0 branch based on nxauth-1.3.2-1.
+
+nxauth-1.3.2-1
+
+- Opened the 1.3.2 branch.
+
+nxauth-1.3.1-2
+
+- Fixed problem with compilation on systems without
+ X11 includes instaled.
diff --git a/nx-X11/programs/nxauth/COPYING b/nx-X11/programs/nxauth/COPYING
new file mode 100644
index 000000000..d511905c1
--- /dev/null
+++ b/nx-X11/programs/nxauth/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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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/nxauth/Imakefile b/nx-X11/programs/nxauth/Imakefile
new file mode 100644
index 000000000..07b1ca752
--- /dev/null
+++ b/nx-X11/programs/nxauth/Imakefile
@@ -0,0 +1,38 @@
+XCOMM $Xorg: Imakefile,v 1.3 2000/08/17 19:54:11 cpqbld Exp $
+
+
+
+
+XCOMM $XFree86: xc/programs/xauth/Imakefile,v 3.5 2001/03/30 02:15:23 keithp Exp $
+
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAUTH, 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+/* LOCAL_LIBRARIES = $(DESTDIR)$(SHLIBDIR)/libXau.a */
+
+
+ INCLUDES=-I../../lib
+ DEPLIBS = $(DEPXAUTHLIB)
+ LOCAL_LIBRARIES = ../../exports/lib/libXau.a
+ SRCS = xauth.c gethost.c process.c parsedpy.c
+ OBJS = xauth.o gethost.o process.o parsedpy.o
+ CONN_DEFINES = $(CONNECTION_FLAGS)
+
+ComplexProgramTarget(nxauth)
+
+SpecialCObjectRule(gethost,$(ICONFIGFILES),$(CONN_DEFINES) $(SIGNAL_DEFINES))
+SpecialCObjectRule(process,$(ICONFIGFILES),$(SIGNAL_DEFINES))
+SpecialCObjectRule(parsedpy,$(ICONFIGFILES),$(CONN_DEFINES))
diff --git a/nx-X11/programs/nxauth/LICENSE b/nx-X11/programs/nxauth/LICENSE
new file mode 100644
index 000000000..626b9c54f
--- /dev/null
+++ b/nx-X11/programs/nxauth/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2001, 2010 NoMachine - http://www.nomachine.com/.
+
+NXAUTH 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 project. Other copy-
+rights 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/nxauth/gethost.c b/nx-X11/programs/nxauth/gethost.c
new file mode 100644
index 000000000..cab2aea9f
--- /dev/null
+++ b/nx-X11/programs/nxauth/gethost.c
@@ -0,0 +1,287 @@
+/*
+ * $Xorg: gethost.c,v 1.5 2001/02/09 02:05:38 xorgcvs 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.
+ * *
+ * Author: Jim Fulton, MIT X Consortium
+ */
+
+/* $XFree86: xc/programs/xauth/gethost.c,v 3.16 2001/12/14 20:01:14 dawes Exp $ */
+
+/* sorry, streams support does not really work yet */
+#if defined(STREAMSCONN) && defined(SVR4)
+#undef STREAMSCONN
+#define TCPCONN
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#define EPROTOTYPE WSAEPROTOTYPE
+#endif
+#include <X11/X.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <ctype.h>
+#ifndef __TYPES__
+#include <sys/types.h>
+#define __TYPES__
+#endif
+#ifndef WIN32
+#ifndef STREAMSCONN
+#ifndef Lynx
+#include <sys/socket.h>
+#else
+#include <socket.h>
+#endif
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef SYSV
+#ifdef i386
+#ifndef sco
+#include <net/errno.h>
+#endif /* !sco */
+#endif /* i386 */
+#endif /* SYSV */
+#endif /* !STREAMSCONN */
+#endif /* !WIN32 */
+#include <errno.h>
+#include "xauth.h"
+
+#ifdef DNETCONN
+#include <netdnet/dn.h>
+#include <netdnet/dnetdb.h>
+#endif
+
+#ifdef SIGALRM
+Bool nameserver_timedout = False;
+
+
+/*
+ * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU)
+ * or a string representing the address (18.58.0.13) if the name cannot
+ * be found. Stolen from xhost.
+ */
+
+static jmp_buf env;
+static
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+nameserver_lost(int sig)
+{
+ nameserver_timedout = True;
+ longjmp (env, -1);
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+#endif
+
+char *
+get_hostname (auth)
+ Xauth *auth;
+{
+ static struct hostent *hp = NULL;
+#ifdef DNETCONN
+ struct nodeent *np;
+ static char nodeaddr[4 + 2 * DN_MAXADDL];
+#endif /* DNETCONN */
+
+ if (auth->address_length == 0)
+ return "Illegal Address";
+#ifdef TCPCONN
+ if (auth->family == FamilyInternet) {
+#ifdef SIGALRM
+ /* gethostbyaddr can take a LONG time if the host does not exist.
+ Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
+ that something is wrong and do not make the user wait.
+ gethostbyaddr will continue after a signal, so we have to
+ jump out of it.
+ */
+ nameserver_timedout = False;
+ signal (SIGALRM, nameserver_lost);
+ alarm (4);
+ if (setjmp(env) == 0) {
+#endif
+ hp = gethostbyaddr (auth->address, auth->address_length, AF_INET);
+#ifdef SIGALRM
+ }
+ alarm (0);
+#endif
+ if (hp)
+ return (hp->h_name);
+ else
+ return (inet_ntoa(*((struct in_addr *)(auth->address))));
+ }
+#endif
+#ifdef DNETCONN
+ if (auth->family == FamilyDECnet) {
+ struct dn_naddr *addr_ptr = (struct dn_naddr *) auth->address;
+
+ if (np = getnodebyaddr(addr_ptr->a_addr, addr_ptr->a_len, AF_DECnet)) {
+ sprintf(nodeaddr, "%s:", np->n_name);
+ } else {
+ sprintf(nodeaddr, "%s:", dnet_htoa(auth->address));
+ }
+ return(nodeaddr);
+ }
+#endif
+
+ return (NULL);
+}
+
+#ifdef TCPCONN
+/*
+ * cribbed from lib/X/XConnDis.c
+ */
+static Bool
+get_inet_address(char *name, unsigned int *resultp)
+{
+ unsigned int hostinetaddr = inet_addr (name);
+ struct hostent *host_ptr;
+ struct sockaddr_in inaddr; /* dummy variable for size calcs */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+
+ if (hostinetaddr == INADDR_NONE) {
+ if ((host_ptr = gethostbyname (name)) == NULL) {
+ /* No such host! */
+ errno = EINVAL;
+ return False;
+ }
+ /* Check the address type for an internet host. */
+ if (host_ptr->h_addrtype != AF_INET) {
+ /* Not an Internet host! */
+ errno = EPROTOTYPE;
+ return False;
+ }
+
+ memmove( (char *)&hostinetaddr, (char *)host_ptr->h_addr,
+ sizeof(inaddr.sin_addr));
+ }
+ *resultp = hostinetaddr;
+ return True;
+}
+#endif
+
+#ifdef DNETCONN
+static Bool get_dnet_address (name, resultp)
+ char *name;
+ struct dn_naddr *resultp;
+{
+ struct dn_naddr *dnaddrp, dnaddr;
+ struct nodeent *np;
+
+ if (dnaddrp = dnet_addr (name)) { /* stolen from xhost */
+ dnaddr = *dnaddrp;
+ } else {
+ if ((np = getnodebyname (name)) == NULL) return False;
+ dnaddr.a_len = np->n_length;
+ memmove( dnaddr.a_addr, np->n_addr, np->n_length);
+ }
+ *resultp = dnaddr;
+ return True;
+}
+#endif
+
+char *get_address_info (family, fulldpyname, prefix, host, lenp)
+ int family;
+ char *fulldpyname;
+ int prefix;
+ char *host;
+ int *lenp;
+{
+ char *retval = NULL;
+ int len = 0;
+ char *src = NULL;
+#ifdef TCPCONN
+ unsigned int hostinetaddr;
+#endif
+#ifdef DNETCONN
+ struct dn_naddr dnaddr;
+#endif
+ char buf[255];
+
+ /*
+ * based on the family, set the pointer src to the start of the address
+ * information to be copied and set len to the number of bytes.
+ */
+ switch (family) {
+ case FamilyLocal: /* hostname/unix:0 */
+ /* handle unix:0 and :0 specially */
+ if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 ||
+ fulldpyname[0] == ':')) {
+
+ if (!get_local_hostname (buf, sizeof buf)) {
+ len = 0;
+ } else {
+ src = buf;
+ len = strlen (buf);
+ }
+ } else {
+ src = fulldpyname;
+ len = prefix;
+ }
+ break;
+ case FamilyInternet: /* host:0 */
+#ifdef TCPCONN
+ if (!get_inet_address (host, &hostinetaddr)) return NULL;
+ src = (char *) &hostinetaddr;
+ len = 4; /* sizeof inaddr.sin_addr, would fail on Cray */
+ break;
+#else
+ return NULL;
+#endif
+ case FamilyDECnet: /* host::0 */
+#ifdef DNETCONN
+ if (!get_dnet_address (host, &dnaddr)) return NULL;
+ src = (char *) &dnaddr;
+ len = (sizeof dnaddr);
+ break;
+#else
+ /* fall through since we don't have code for it */
+#endif
+ default:
+ src = NULL;
+ len = 0;
+ }
+
+ /*
+ * if source was provided, allocate space and copy it
+ */
+ if (len == 0 || !src) return NULL;
+
+ retval = malloc (len);
+ if (retval) {
+ memmove( retval, src, len);
+ *lenp = len;
+ }
+ return retval;
+}
diff --git a/nx-X11/programs/nxauth/nxauth.man b/nx-X11/programs/nxauth/nxauth.man
new file mode 100644
index 000000000..a414afad4
--- /dev/null
+++ b/nx-X11/programs/nxauth/nxauth.man
@@ -0,0 +1,236 @@
+.\" $Xorg: xauth.man,v 1.4 2001/02/09 02:05:38 xorgcvs Exp $
+.\" Copyright 1993, 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.
+.\"
+.\" $XFree86: xc/programs/xauth/xauth.man,v 1.7 2001/12/14 20:01:15 dawes Exp $
+.\"
+.TH XAUTH 1 __xorgversion__
+.SH NAME
+xauth \- X authority file utility
+.SH SYNOPSIS
+.B xauth
+[ \fB\-f\fP \fIauthfile\fP ] [ \fB\-vqib\fP ] [ \fIcommand arg ...\fP ]
+.SH DESCRIPTION
+.PP
+The \fIxauth\fP program is used to edit and display the authorization
+information used in connecting to the X server. This program is usually
+used to extract authorization records from one machine and merge them in on
+another (as is the case when using remote logins or granting access to
+other users). Commands (described below) may be entered interactively,
+on the \fIxauth\fP command line, or in scripts. Note that this program
+does \fBnot\fP contact the X server except when the generate command is used.
+Normally \fIxauth\fP is not used to create the authority file entry in
+the first place; \fIxdm\fP does that.
+.SH OPTIONS
+The following options may be used with \fIxauth\fP. They may be given
+individually (e.g., \fI\-q \-i\|\fP) or may combined (e.g., \fI\-qi\|\fP).
+.TP 8
+.B "\-f \fIauthfile\fP"
+This option specifies the name of the authority file to use. By default,
+\fIxauth\fP will use the file specified by the XAUTHORITY environment variable
+or \fI\.Xauthority\fP in the user's home directory.
+.TP 8
+.B \-q
+This option indicates that \fIxauth\fP should operate quietly and not print
+unsolicited status messages. This is the default if an \fIxauth\fP command is
+is given on the command line or if the standard output is not directed to a
+terminal.
+.TP 8
+.B \-v
+This option indicates that \fIxauth\fP should operate verbosely and print
+status messages indicating the results of various operations (e.g., how many
+records have been read in or written out). This is the default if \fIxauth\fP
+is reading commands from its standard input and its standard output is
+directed to a terminal.
+.TP 8
+.B \-i
+This option indicates that \fIxauth\fP should ignore any authority file
+locks. Normally, \fIxauth\fP will refuse to read or edit any authority files
+that have been locked by other programs (usually \fIxdm\fP or another
+\fIxauth\fP).
+.TP 8
+.B \-b
+This option indicates that \fIxauth\fP should attempt to break any authority
+file locks before proceeding. Use this option only to clean up stale locks.
+.SH COMMANDS
+The following commands may be used to manipulate authority files:
+.TP 8
+.B "add \fIdisplayname protocolname hexkey"
+An authorization entry for the indicated display using the given protocol
+and key data is added to the authorization file. The data is specified as
+an even-lengthed string of hexadecimal digits, each pair representing
+one octet. The first digit of each pair gives the most significant 4 bits
+of the octet, and the second digit of the pair gives the least significant 4
+bits. For example, a 32 character hexkey would represent a 128-bit value.
+A protocol name consisting of just a
+single period is treated as an abbreviation for \fIMIT-MAGIC-COOKIE-1\fP.
+
+.TP 8
+.B "generate \fIdisplayname protocolname\fP \fR[\fPtrusted|untrusted\fR]\fP"
+.B \fR[\fPtimeout \fIseconds\fP\fR]\fP \fR[\fPgroup \fIgroup-id\fP\fR]\fP \fR[\fBdata \fIhexdata\fR]
+
+This command is similar to add. The main difference is that instead
+of requiring the user to supply the key data, it connects to the
+server specified in \fIdisplayname\fP and uses the SECURITY extension
+in order to get the key data to store in the authorization file. If
+the server cannot be contacted or if it does not support the SECURITY
+extension, the command fails. Otherwise, an authorization entry for
+the indicated display using the given protocol is added to the
+authorization file. A protocol name consisting of just a single
+period is treated as an abbreviation for \fIMIT-MAGIC-COOKIE-1\fP.
+
+If the \fBtrusted\fP option is used, clients that connect using this
+authorization will have full run of the display, as usual. If
+\fBuntrusted\fP is used, clients that connect using this authorization
+will be considered untrusted and prevented from stealing or tampering
+with data belonging to trusted clients. See the SECURITY extension
+specification for full details on the restrictions imposed on
+untrusted clients. The default is \fBuntrusted\fP.
+
+The \fBtimeout\fP option specifies how long in seconds this
+authorization will be valid. If the authorization remains unused (no
+clients are connected with it) for longer than this time period, the
+server purges the authorization, and future attempts to connect using
+it will fail. Note that the purging done by the server does \fBnot\fP
+delete the authorization entry from the authorization file. The
+default timeout is 60 seconds.
+
+The \fBgroup\fP option specifies the application group that clients
+connecting with this authorization should belong to. See the
+application group extension specification for more details. The
+default is to not belong to an application group.
+
+The \fBdata\fP option specifies data that the server should use to
+generate the authorization. Note that this is \fBnot\fP the same data
+that gets written to the authorization file. The interpretation of
+this data depends on the authorization protocol. The \fIhexdata\fP is
+in the same format as the \fIhexkey\fP described in the add command.
+The default is to send no data.
+
+.TP 8
+.B "[n]extract \fIfilename displayname..."
+Authorization entries for each of the specified displays are written to the
+indicated file. If the \fInextract\fP command is used, the entries are written
+in a numeric format suitable for non-binary transmission (such as secure
+electronic mail). The extracted entries can be read back in using the
+\fImerge\fP and \fInmerge\fP commands. If the filename consists of
+just a single dash, the entries will be written to the standard output.
+.TP 8
+.B "[n]list \fR[\fIdisplayname\fP...]"
+Authorization entries for each of the specified displays (or all if no
+displays are named) are printed on the standard output. If the \fInlist\fP
+command is used, entries will be shown in the numeric format used by
+the \fInextract\fP command; otherwise, they are shown in a textual format.
+Key data is always displayed in the hexadecimal format given in the
+description of the \fIadd\fP command.
+.TP 8
+.B "[n]merge \fR[\fIfilename\fP...]"
+Authorization entries are read from the specified files and are merged into
+the authorization database, superceding any matching existing entries. If
+the \fInmerge\fP command is used, the numeric format given in the description
+of the \fIextract\fP command is used. If a filename consists of just a single
+dash, the standard input will be read if it hasn't been read before.
+.TP 8
+.B "remove \fIdisplayname\fR..."
+Authorization entries matching the specified displays are removed from the
+authority file.
+.TP 8
+.B "source \fIfilename"
+The specified file is treated as a script containing \fIxauth\fP commands
+to execute. Blank lines and lines beginning with a sharp sign (#) are
+ignored. A single dash may be used to indicate the standard input, if it
+hasn't already been read.
+.TP 8
+.B "info"
+Information describing the authorization file, whether or not any changes
+have been made, and from where \fIxauth\fP commands are being read
+is printed on the standard output.
+.TP 8
+.B "exit"
+If any modifications have been made, the authority file is written out (if
+allowed), and the program exits. An end of file is treated as an implicit
+\fIexit\fP command.
+.TP 8
+.B "quit"
+The program exits, ignoring any modifications. This may also be accomplished
+by pressing the interrupt character.
+.TP 8
+.B "help [\fIstring\fP]"
+A description of all commands that begin with the given string (or all
+commands if no string is given) is printed on the standard output.
+.TP 8
+.B "?"
+A short list of the valid commands is printed on the standard output.
+.SH "DISPLAY NAMES"
+Display names for the \fIadd\fP, \fI[n]extract\fP, \fI[n]list\fP,
+\fI[n]merge\fP, and \fIremove\fP commands use the same format as the
+DISPLAY environment variable and the common \fI\-display\fP command line
+argument. Display-specific information (such as the screen number)
+is unnecessary and will be ignored.
+Same-machine connections (such as local-host sockets,
+shared memory, and the Internet Protocol hostname \fIlocalhost\fP) are
+referred to as \fIhostname\fP/unix:\fIdisplaynumber\fP so that
+local entries for different machines may be stored in one authority file.
+.SH EXAMPLE
+.PP
+The most common use for \fIxauth\fP is to extract the entry for the
+current display, copy it to another machine, and merge it into the
+user's authority file on the remote machine:
+.sp
+.nf
+ % xauth extract \- $DISPLAY | rsh otherhost xauth merge \-
+.fi
+.PP
+.sp
+The following command contacts the server :0 to create an
+authorization using the MIT-MAGIC-COOKIE-1 protocol. Clients that
+connect with this authorization will be untrusted.
+.nf
+ % xauth generate :0 .
+.fi
+.SH ENVIRONMENT
+This \fIxauth\fP program uses the following environment variables:
+.TP 8
+.B XAUTHORITY
+to get the name of the authority file to use if the \fI\-f\fP option isn't
+used.
+.TP 8
+.B HOME
+to get the user's home directory if XAUTHORITY isn't defined.
+.SH FILES
+.TP 8
+.I $HOME/.Xauthority
+default authority file if XAUTHORITY isn't defined.
+.SH BUGS
+.PP
+Users that have unsecure networks should take care to use encrypted
+file transfer mechanisms to copy authorization entries between machines.
+Similarly, the \fIMIT-MAGIC-COOKIE-1\fP protocol is not very useful in
+unsecure environments. Sites that are interested in additional security
+may need to use encrypted authorization mechanisms such as Kerberos.
+.PP
+Spaces are currently not allowed in the protocol name. Quoting could be
+added for the truly perverse.
+.SH AUTHOR
+Jim Fulton, MIT X Consortium
diff --git a/nx-X11/programs/nxauth/parsedpy.c b/nx-X11/programs/nxauth/parsedpy.c
new file mode 100644
index 000000000..8ce46815c
--- /dev/null
+++ b/nx-X11/programs/nxauth/parsedpy.c
@@ -0,0 +1,259 @@
+/*
+ * $Xorg: parsedpy.c,v 1.4 2001/02/09 02:05:38 xorgcvs Exp $
+ *
+ * parse_displayname - utility routine for splitting up display name strings
+ *
+ *
+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.
+ * *
+ * Author: Jim Fulton, MIT X Consortium
+ */
+
+/* $XFree86: xc/programs/xauth/parsedpy.c,v 3.6 2001/12/14 20:01:15 dawes Exp $ */
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAUTH, 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h> /* for NULL */
+#include <ctype.h> /* for isascii() and isdigit() */
+#include <X11/Xos.h> /* for strchr() and string routines */
+#include <X11/Xlib.h> /* for Family contants */
+#ifdef hpux
+#include <sys/utsname.h> /* for struct utsname */
+#endif
+#include <X11/Xauth.h> /* for FamilyLocal */
+
+#if defined(UNIXCONN) || defined(LOCALCONN)
+#define UNIX_CONNECTION "unix"
+#define UNIX_CONNECTION_LENGTH 4
+#endif
+
+#include <stdlib.h>
+#include "xauth.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * private utility routines
+ */
+
+char *
+copystring (char *src, int len)
+{
+ char *cp;
+
+ if (!src && len != 0) return NULL;
+ cp = malloc (len + 1);
+ if (cp) {
+ if (src) strncpy (cp, src, len);
+ cp[len] = '\0';
+ }
+ return cp;
+}
+
+
+char *
+get_local_hostname (char *buf, int maxlen)
+{
+ buf[0] = '\0';
+/*
+ (void) XmuGetHostname (buf, maxlen);
+*/
+ /*FIXME*/
+
+ (void) gethostname (buf, maxlen);
+
+ buf [maxlen - 1] = '\0';
+
+ #ifdef TEST
+ printf("get_local_hostname: Host name is %s", buf);
+ #endif
+
+ return (buf[0] ? buf : NULL);
+}
+
+#ifndef UNIXCONN
+static char *
+copyhostname (void)
+{
+ char buf[256];
+
+ return (get_local_hostname (buf, sizeof buf) ?
+ copystring (buf, strlen (buf)) : NULL);
+}
+#endif
+
+/*
+ * parse_displayname - display a display string up into its component parts
+ */
+Bool
+parse_displayname (char *displayname,
+ int *familyp, /* return */
+ char **hostp, /* return */
+ int *dpynump, /* return */
+ int *scrnump, /* return */
+ char **restp) /* return */
+{
+ char *ptr; /* work variables */
+ int len; /* work variable */
+ int family = -1; /* value to be returned */
+ char *host = NULL; /* must free if set and error return */
+ int dpynum = -1; /* value to be returned */
+ int scrnum = 0; /* value to be returned */
+ char *rest = NULL; /* must free if set and error return */
+ Bool dnet = False; /* if true then using DECnet */
+
+ /* check the name */
+ if (!displayname || !displayname[0]) return False;
+
+ /* must have at least :number */
+ ptr = strchr(displayname, ':');
+ if (!ptr || !ptr[1]) return False;
+ if (ptr[1] == ':') {
+ if (ptr[2] == '\0') return False;
+ dnet = True;
+ }
+
+
+ /*
+ * get the host string; if none is given, use the most effiecient path
+ */
+
+ len = (ptr - displayname); /* length of host name */
+ if (len == 0) { /* choose most efficient path */
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
+ family = FamilyLocal;
+#else
+ if (dnet) {
+ host = copystring ("0", 1);
+ family = FamilyDECnet;
+ } else {
+ host = copyhostname ();
+ family = FamilyInternet;
+ }
+#endif
+ } else {
+ host = copystring (displayname, len);
+ if (dnet) {
+ family = dnet;
+ } else {
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ if (host && strcmp (host, UNIX_CONNECTION) == 0)
+ family = FamilyLocal;
+ else
+#endif
+ family = FamilyInternet;
+ }
+ }
+
+ if (!host) return False;
+
+
+ /*
+ * get the display number; we know that there is something after the
+ * colon (or colons) from above. note that host is now set and must
+ * be freed if there is an error.
+ */
+
+ if (dnet) ptr++; /* skip the extra DECnet colon */
+ ptr++; /* move to start of display num */
+ {
+ register char *cp;
+
+ for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
+ len = (cp - ptr);
+ /* check present and valid follow */
+ if (len == 0 || (*cp && *cp != '.')) {
+ free (host);
+ return False;
+ }
+
+ dpynum = atoi (ptr); /* it will handle num. as well */
+ ptr = cp;
+ }
+
+ /*
+ * now get screen number if given; ptr may point to nul at this point
+ */
+ if (ptr[0] == '.') {
+ register char *cp;
+
+ ptr++;
+ for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
+ len = (cp - ptr);
+ if (len == 0 || (*cp && *cp != '.')) { /* all prop name */
+ free (host);
+ return False;
+ }
+
+ scrnum = atoi (ptr); /* it will handle num. as well */
+ ptr = cp;
+ }
+
+ /*
+ * and finally, get any additional stuff that might be following the
+ * the screen number; ptr must point to a period if there is anything
+ */
+
+ if (ptr[0] == '.') {
+ ptr++;
+ len = strlen (ptr);
+ if (len > 0) {
+ rest = copystring (ptr, len);
+ if (!rest) {
+ free (host);
+ return False;
+ }
+ }
+ }
+
+ /*
+ * and we are done!
+ */
+
+ *familyp = family;
+ *hostp = host;
+ *dpynump = dpynum;
+ *scrnump = scrnum;
+ *restp = rest;
+ return True;
+}
+
+
diff --git a/nx-X11/programs/nxauth/process.c b/nx-X11/programs/nxauth/process.c
new file mode 100644
index 000000000..57090e23e
--- /dev/null
+++ b/nx-X11/programs/nxauth/process.c
@@ -0,0 +1,1872 @@
+/* $Xorg: process.c,v 1.6 2001/02/09 02:05:38 xorgcvs 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.
+
+*/
+/* $XFree86: xc/programs/xauth/process.c,v 3.18 2003/02/13 02:50:22 dawes Exp $ */
+
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAUTH, 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+/*
+ * Author: Jim Fulton, MIT X Consortium
+ */
+
+#include "xauth.h"
+#include <ctype.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <signal.h>
+/*#include <X11/X.h>*/ /* for Family constants */
+/*
+#include <X11/Xlib.h>
+#include <X11/extensions/security.h>
+*/
+
+/*FIXME*/
+#define FamilyInternet 0
+#define FamilyDECnet 1
+
+extern Bool naneserver_timedout;
+
+#ifndef DEFAULT_PROTOCOL_ABBREV /* to make add command easier */
+#define DEFAULT_PROTOCOL_ABBREV "."
+#endif
+#ifndef DEFAULT_PROTOCOL /* for protocol abbreviation */
+#define DEFAULT_PROTOCOL "MIT-MAGIC-COOKIE-1"
+#endif
+
+#define SECURERPC "SUN-DES-1"
+#define K5AUTH "MIT-KERBEROS-5"
+
+#define XAUTH_DEFAULT_RETRIES 10 /* number of competitors we expect */
+#define XAUTH_DEFAULT_TIMEOUT 2 /* in seconds, be quick */
+#define XAUTH_DEFAULT_DEADTIME 600L /* 10 minutes in seconds */
+
+typedef struct _AuthList { /* linked list of entries */
+ struct _AuthList *next;
+ Xauth *auth;
+} AuthList;
+
+typedef int (*ProcessFunc)(char *, int, int, char**);
+
+#define add_to_list(h,t,e) {if (t) (t)->next = (e); else (h) = (e); (t) = (e);}
+
+typedef struct _CommandTable { /* commands that are understood */
+ char *name; /* full name */
+ int minlen; /* unique prefix */
+ int maxlen; /* strlen(name) */
+ ProcessFunc processfunc; /* handler */
+ char *helptext; /* what to print for help */
+} CommandTable;
+
+struct _extract_data { /* for iterating */
+ FILE *fp; /* input source */
+ char *filename; /* name of input */
+ Bool used_stdout; /* whether or not need to close */
+ Bool numeric; /* format in which to write */
+ int nwritten; /* number of entries written */
+ char *cmd; /* for error messages */
+};
+
+struct _list_data { /* for iterating */
+ FILE *fp; /* output file */
+ Bool numeric; /* format in which to write */
+};
+
+
+/*
+ * private data
+ */
+static char *stdin_filename = "(stdin)"; /* for messages */
+static char *stdout_filename = "(stdout)"; /* for messages */
+static char *Yes = "yes"; /* for messages */
+static char *No = "no"; /* for messages */
+
+static int do_help ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_questionmark ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_list ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_merge ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_extract ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_add ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_remove ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_info ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_exit ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_quit ( char *inputfilename, int lineno, int argc, char **argv );
+static int do_source ( char *inputfilename, int lineno, int argc, char **argv );
+/*
+static int do_generate ( char *inputfilename, int lineno, int argc, char **argv );
+*/
+static CommandTable command_table[] = { /* table of known commands */
+ { "add", 2, 3, do_add,
+ "add dpyname protoname hexkey add entry" },
+ { "exit", 3, 4, do_exit,
+ "exit save changes and exit program" },
+ { "extract", 3, 7, do_extract,
+ "extract filename dpyname... extract entries into file" },
+ { "help", 1, 4, do_help,
+ "help [topic] print help" },
+ { "info", 1, 4, do_info,
+ "info print information about entries" },
+ { "list", 1, 4, do_list,
+ "list [dpyname...] list entries" },
+ { "merge", 1, 5, do_merge,
+ "merge filename... merge entries from files" },
+ { "nextract", 2, 8, do_extract,
+ "nextract filename dpyname... numerically extract entries" },
+ { "nlist", 2, 5, do_list,
+ "nlist [dpyname...] numerically list entries" },
+ { "nmerge", 2, 6, do_merge,
+ "nmerge filename... numerically merge entries" },
+ { "quit", 1, 4, do_quit,
+ "quit abort changes and exit program" },
+ { "remove", 1, 6, do_remove,
+ "remove dpyname... remove entries" },
+ { "source", 1, 6, do_source,
+ "source filename read commands from file" },
+ { "?", 1, 1, do_questionmark,
+ "? list available commands" },
+/* { "generate", 1, 8, do_generate,
+ "generate dpyname protoname [options] use server to generate entry\n"
+ " options are:\n"
+ " timeout n authorization expiration time in seconds\n"
+ " trusted clients using this entry are trusted\n"
+ " untrusted clients using this entry are untrusted\n"
+ " group n clients using this entry belong to application group n\n"
+ " data hexkey auth protocol specific data needed to generate the entry\n"
+ }, */
+ { NULL, 0, 0, NULL, NULL },
+};
+
+#define COMMAND_NAMES_PADDED_WIDTH 10 /* wider than anything above */
+
+
+static Bool okay_to_use_stdin = True; /* set to false after using */
+
+static char *hex_table[] = { /* for printing hex digits */
+ "00", "01", "02", "03", "04", "05", "06", "07",
+ "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
+ "10", "11", "12", "13", "14", "15", "16", "17",
+ "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
+ "20", "21", "22", "23", "24", "25", "26", "27",
+ "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
+ "30", "31", "32", "33", "34", "35", "36", "37",
+ "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
+ "40", "41", "42", "43", "44", "45", "46", "47",
+ "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
+ "50", "51", "52", "53", "54", "55", "56", "57",
+ "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
+ "60", "61", "62", "63", "64", "65", "66", "67",
+ "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
+ "70", "71", "72", "73", "74", "75", "76", "77",
+ "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
+ "80", "81", "82", "83", "84", "85", "86", "87",
+ "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
+ "90", "91", "92", "93", "94", "95", "96", "97",
+ "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
+ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
+ "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
+ "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7",
+ "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "da", "db", "dc", "dd", "de", "df",
+ "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
+ "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
+};
+
+static unsigned int hexvalues[256]; /* for parsing hex input */
+
+static int original_umask = 0; /* for restoring */
+
+
+/*
+ * private utility procedures
+ */
+
+static void
+prefix(char *fn, int n)
+{
+ fprintf (stderr, "%s: %s:%d: ", ProgramName, fn, n);
+}
+
+static void
+baddisplayname(char *dpy, char *cmd)
+{
+ fprintf (stderr, "bad display name \"%s\" in \"%s\" command\n",
+ dpy, cmd);
+}
+
+static void
+badcommandline(char *cmd)
+{
+ fprintf (stderr, "bad \"%s\" command line\n", cmd);
+}
+
+static char *
+skip_space(register char *s)
+{
+ if (!s) return NULL;
+
+ for ( ; *s && isascii(*s) && isspace(*s); s++)
+ ;
+ return s;
+}
+
+
+static char *
+skip_nonspace(register char *s)
+{
+ if (!s) return NULL;
+
+ /* put quoting into loop if need be */
+ for ( ; *s && isascii(*s) && !isspace(*s); s++)
+ ;
+ return s;
+}
+
+static char **
+split_into_words(char *src, int *argcp) /* argvify string */
+{
+ char *jword;
+ char savec;
+ char **argv;
+ int cur, total;
+
+ *argcp = 0;
+#define WORDSTOALLOC 4 /* most lines are short */
+ argv = (char **) malloc (WORDSTOALLOC * sizeof (char *));
+ if (!argv) return NULL;
+ cur = 0;
+ total = WORDSTOALLOC;
+
+ /*
+ * split the line up into separate, nul-terminated tokens; the last
+ * "token" will point to the empty string so that it can be bashed into
+ * a null pointer.
+ */
+
+ do {
+ jword = skip_space (src);
+ src = skip_nonspace (jword);
+ savec = *src;
+ *src = '\0';
+ if (cur == total) {
+ total += WORDSTOALLOC;
+ argv = (char **) realloc (argv, total * sizeof (char *));
+ if (!argv) return NULL;
+ }
+ argv[cur++] = jword;
+ if (savec) src++; /* if not last on line advance */
+ } while (jword != src);
+
+ argv[--cur] = NULL; /* smash empty token to end list */
+ *argcp = cur;
+ return argv;
+}
+
+
+static FILE *
+open_file(char **filenamep,
+ char *mode,
+ Bool *usedstdp,
+ char *srcfn,
+ int srcln,
+ char *cmd)
+{
+ FILE *fp;
+
+ if (strcmp (*filenamep, "-") == 0) {
+ *usedstdp = True;
+ /* select std descriptor to use */
+ if (mode[0] == 'r') {
+ if (okay_to_use_stdin) {
+ okay_to_use_stdin = False;
+ *filenamep = stdin_filename;
+ return stdin;
+ } else {
+ prefix (srcfn, srcln);
+ fprintf (stderr, "%s: stdin already in use\n", cmd);
+ return NULL;
+ }
+ } else {
+ *filenamep = stdout_filename;
+ return stdout; /* always okay to use stdout */
+ }
+ }
+
+ fp = fopen (*filenamep, mode);
+ if (!fp) {
+ prefix (srcfn, srcln);
+ fprintf (stderr, "%s: unable to open file %s\n", cmd, *filenamep);
+ }
+ return fp;
+}
+
+static int
+getinput(FILE *fp)
+{
+ register int c;
+
+ while ((c = getc (fp)) != EOF && isascii(c) && c != '\n' && isspace(c)) ;
+ return c;
+}
+
+static int
+get_short(FILE *fp, unsigned short *sp) /* for reading numeric input */
+{
+ int c;
+ int i;
+ unsigned short us = 0;
+
+ /*
+ * read family: written with %04x
+ */
+ for (i = 0; i < 4; i++) {
+ switch (c = getinput (fp)) {
+ case EOF:
+ case '\n':
+ return 0;
+ }
+ if (c < 0 || c > 255) return 0;
+ us = (us * 16) + hexvalues[c]; /* since msb */
+ }
+ *sp = us;
+ return 1;
+}
+
+static int
+get_bytes(FILE *fp, unsigned int n, char **ptr) /* for reading numeric input */
+{
+ char *s;
+ register char *cp;
+ int c1, c2;
+
+ cp = s = malloc (n);
+ if (!cp) return 0;
+
+ while (n > 0) {
+ if ((c1 = getinput (fp)) == EOF || c1 == '\n' ||
+ (c2 = getinput (fp)) == EOF || c2 == '\n') {
+ free (s);
+ return 0;
+ }
+ *cp = (char) ((hexvalues[c1] * 16) + hexvalues[c2]);
+ cp++;
+ n--;
+ }
+
+ *ptr = s;
+ return 1;
+}
+
+
+static Xauth *
+read_numeric(FILE *fp)
+{
+ Xauth *auth;
+
+ auth = (Xauth *) malloc (sizeof (Xauth));
+ if (!auth) goto bad;
+ auth->family = 0;
+ auth->address = NULL;
+ auth->address_length = 0;
+ auth->number = NULL;
+ auth->number_length = 0;
+ auth->name = NULL;
+ auth->name_length = 0;
+ auth->data = NULL;
+ auth->data_length = 0;
+
+ if (!get_short (fp, (unsigned short *) &auth->family))
+ goto bad;
+ if (!get_short (fp, (unsigned short *) &auth->address_length))
+ goto bad;
+ if (!get_bytes (fp, (unsigned int) auth->address_length, &auth->address))
+ goto bad;
+ if (!get_short (fp, (unsigned short *) &auth->number_length))
+ goto bad;
+ if (!get_bytes (fp, (unsigned int) auth->number_length, &auth->number))
+ goto bad;
+ if (!get_short (fp, (unsigned short *) &auth->name_length))
+ goto bad;
+ if (!get_bytes (fp, (unsigned int) auth->name_length, &auth->name))
+ goto bad;
+ if (!get_short (fp, (unsigned short *) &auth->data_length))
+ goto bad;
+ if (!get_bytes (fp, (unsigned int) auth->data_length, &auth->data))
+ goto bad;
+
+ switch (getinput (fp)) { /* get end of line */
+ case EOF:
+ case '\n':
+ return auth;
+ }
+
+ bad:
+ if (auth) XauDisposeAuth (auth); /* won't free null pointers */
+ return NULL;
+}
+
+typedef Xauth *(*ReadFunc)(FILE *);
+
+static int
+read_auth_entries(FILE *fp, Bool numeric, AuthList **headp, AuthList **tailp)
+{
+ ReadFunc readfunc = (numeric ? read_numeric : XauReadAuth);
+ Xauth *auth;
+ AuthList *head, *tail;
+ int n;
+
+ head = tail = NULL;
+ n = 0;
+ /* put all records into linked list */
+ while ((auth = ((*readfunc) (fp))) != NULL) {
+ AuthList *l = (AuthList *) malloc (sizeof (AuthList));
+ if (!l) {
+ fprintf (stderr,
+ "%s: unable to alloc entry reading auth file\n",
+ ProgramName);
+ exit (1);
+ }
+ l->next = NULL;
+ l->auth = auth;
+ if (tail) /* if not first time through append */
+ tail->next = l;
+ else
+ head = l; /* first time through, so assign */
+ tail = l;
+ n++;
+ }
+ *headp = head;
+ *tailp = tail;
+ return n;
+}
+
+static Bool
+get_displayname_auth(char *displayname, Xauth *auth)
+{
+ int family;
+ char *host = NULL, *rest = NULL;
+ int dpynum, scrnum;
+ char *cp;
+ int len;
+ Xauth proto;
+ int prelen = 0;
+
+ /*
+ * check to see if the display name is of the form "host/unix:"
+ * which is how the list routine prints out local connections
+ */
+ cp = strchr(displayname, '/');
+ if (cp && strncmp (cp, "/unix:", 6) == 0)
+ prelen = (cp - displayname);
+
+ #ifdef __APPLE__
+
+ /*
+ * FIXME: This is an attempt to get the right
+ * cookie, because no one can grant that the
+ * X server is running on the display number
+ * reported in the launchd display name.
+ */
+
+ if (strncmp (displayname, "/tmp/launch", 11) == 0)
+ displayname = strrchr(displayname, ':');
+
+ #endif
+
+ if (!parse_displayname (displayname + ((prelen > 0) ? prelen + 1 : 0),
+ &family, &host, &dpynum, &scrnum, &rest)) {
+ return False;
+ }
+
+ proto.family = family;
+ proto.address = get_address_info (family, displayname, prelen, host, &len);
+ if (proto.address) {
+ char buf[40]; /* want to hold largest display num */
+
+ proto.address_length = len;
+ buf[0] = '\0';
+ sprintf (buf, "%d", dpynum);
+ proto.number_length = strlen (buf);
+ if (proto.number_length <= 0) {
+ free (proto.address);
+ proto.address = NULL;
+ } else {
+ proto.number = copystring (buf, proto.number_length);
+ }
+ }
+
+ if (host) free (host);
+ if (rest) free (rest);
+
+ if (proto.address) {
+ auth->family = proto.family;
+ auth->address = proto.address;
+ auth->address_length = proto.address_length;
+ auth->number = proto.number;
+ auth->number_length = proto.number_length;
+ auth->name = NULL;
+ auth->name_length = 0;
+ auth->data = NULL;
+ auth->data_length = 0;
+ return True;
+ } else {
+ return False;
+ }
+}
+
+static int
+cvthexkey(char *hexstr, char **ptrp) /* turn hex key string into octets */
+{
+ int i;
+ int len = 0;
+ char *retval, *s;
+ unsigned char *us;
+ char c;
+ char savec = '\0';
+
+ /* count */
+ for (s = hexstr; *s; s++) {
+ if (!isascii(*s)) return -1;
+ if (isspace(*s)) continue;
+ if (!isxdigit(*s)) return -1;
+ len++;
+ }
+
+ /* if odd then there was an error */
+ if ((len & 1) == 1) return -1;
+
+
+ /* now we know that the input is good */
+ len >>= 1;
+ retval = malloc (len);
+ if (!retval) {
+ fprintf (stderr, "%s: unable to allocate %d bytes for hexkey\n",
+ ProgramName, len);
+ return -1;
+ }
+
+ for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) {
+ c = *hexstr;
+ if (isspace(c)) continue; /* already know it is ascii */
+ if (isupper(c))
+ c = tolower(c);
+ if (savec) {
+#define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10)))
+ *us = (unsigned char)((atoh(savec) << 4) + atoh(c));
+#undef atoh
+ savec = 0; /* ready for next character */
+ us++;
+ i--;
+ } else {
+ savec = c;
+ }
+ }
+ *ptrp = retval;
+ return len;
+}
+
+static int
+dispatch_command(char *inputfilename,
+ int lineno,
+ int argc,
+ char **argv,
+ CommandTable *tab,
+ int *statusp)
+{
+ CommandTable *ct;
+ char *cmd;
+ int n;
+ /* scan table for command */
+ cmd = argv[0];
+ n = strlen (cmd);
+ for (ct = tab; ct->name; ct++) {
+ /* look for unique prefix */
+ if (n >= ct->minlen && n <= ct->maxlen &&
+ strncmp (cmd, ct->name, n) == 0) {
+ *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv);
+ return 1;
+ }
+ }
+
+ *statusp = 1;
+ return 0;
+}
+
+
+static AuthList *xauth_head = NULL; /* list of auth entries */
+static Bool xauth_existed = False; /* if was present at initialize */
+static Bool xauth_modified = False; /* if added, removed, or merged */
+static Bool xauth_allowed = True; /* if allowed to write auth file */
+static Bool xauth_locked = False; /* if has been locked */
+static char *xauth_filename = NULL;
+static Bool dieing = False;
+
+#ifdef SIGNALRETURNSINT
+#define _signal_t int
+#else
+#define _signal_t void
+#endif
+
+/* poor man's puts(), for under signal handlers */
+#define WRITES(fd, S) (void)write((fd), (S), strlen((S)))
+
+/* ARGSUSED */
+static _signal_t
+die(int sig)
+{
+ dieing = True;
+ _exit (auth_finalize ());
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+
+static _signal_t
+catchsig(int sig)
+{
+#ifdef SYSV
+ if (sig > 0) signal (sig, die); /* re-establish signal handler */
+#endif
+ /*
+ * fileno() might not be reentrant, avoid it if possible, and use
+ * stderr instead of stdout
+ */
+#ifdef STDERR_FILENO
+ if (verbose && xauth_modified) WRITES(STDERR_FILENO, "\r\n");
+#else
+ if (verbose && xauth_modified) WRITES(fileno(stderr), "\r\n");
+#endif
+ die (sig);
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+
+static void
+register_signals(void)
+{
+ signal (SIGINT, catchsig);
+ signal (SIGTERM, catchsig);
+#ifdef SIGHUP
+ signal (SIGHUP, catchsig);
+#endif
+ return;
+}
+
+
+/*
+ * public procedures for parsing lines of input
+ */
+
+int
+auth_initialize(char *authfilename)
+{
+ int n;
+ AuthList *head, *tail;
+ FILE *authfp;
+ Bool exists;
+
+ xauth_filename = authfilename; /* used in cleanup, prevent race with
+ signals */
+ register_signals ();
+
+ bzero ((char *) hexvalues, sizeof hexvalues);
+ hexvalues['0'] = 0;
+ hexvalues['1'] = 1;
+ hexvalues['2'] = 2;
+ hexvalues['3'] = 3;
+ hexvalues['4'] = 4;
+ hexvalues['5'] = 5;
+ hexvalues['6'] = 6;
+ hexvalues['7'] = 7;
+ hexvalues['8'] = 8;
+ hexvalues['9'] = 9;
+ hexvalues['a'] = hexvalues['A'] = 0xa;
+ hexvalues['b'] = hexvalues['B'] = 0xb;
+ hexvalues['c'] = hexvalues['C'] = 0xc;
+ hexvalues['d'] = hexvalues['D'] = 0xd;
+ hexvalues['e'] = hexvalues['E'] = 0xe;
+ hexvalues['f'] = hexvalues['F'] = 0xf;
+
+ if (break_locks && verbose) {
+ printf ("Attempting to break locks on authority file %s\n",
+ authfilename);
+ }
+
+ if (ignore_locks) {
+ if (break_locks) XauUnlockAuth (authfilename);
+ } else {
+ n = XauLockAuth (authfilename, XAUTH_DEFAULT_RETRIES,
+ XAUTH_DEFAULT_TIMEOUT,
+ (break_locks ? 0L : XAUTH_DEFAULT_DEADTIME));
+ if (n != LOCK_SUCCESS) {
+ char *reason = "unknown error";
+ switch (n) {
+ case LOCK_ERROR:
+ reason = "error";
+ break;
+ case LOCK_TIMEOUT:
+ reason = "timeout";
+ break;
+ }
+ fprintf (stderr, "%s: %s in locking authority file %s\n",
+ ProgramName, reason, authfilename);
+ return -1;
+ } else
+ xauth_locked = True;
+ }
+
+ /* these checks can only be done reliably after the file is locked */
+ exists = (access (authfilename, F_OK) == 0);
+ if (exists && access (authfilename, W_OK) != 0) {
+ fprintf (stderr,
+ "%s: %s not writable, changes will be ignored\n",
+ ProgramName, authfilename);
+ xauth_allowed = False;
+ }
+
+ original_umask = umask (0077); /* disallow non-owner access */
+
+ authfp = fopen (authfilename, "rb");
+ if (!authfp) {
+ int olderrno = errno;
+
+ /* if file there then error */
+ if (access (authfilename, F_OK) == 0) { /* then file does exist! */
+ errno = olderrno;
+ return -1;
+ } /* else ignore it */
+ fprintf (stderr,
+ "%s: creating new authority file %s\n",
+ ProgramName, authfilename);
+ } else {
+ xauth_existed = True;
+ n = read_auth_entries (authfp, False, &head, &tail);
+ (void) fclose (authfp);
+ if (n < 0) {
+ fprintf (stderr,
+ "%s: unable to read auth entries from file \"%s\"\n",
+ ProgramName, authfilename);
+ return -1;
+ }
+ xauth_head = head;
+ }
+
+ n = strlen (authfilename);
+ xauth_filename = malloc (n + 1);
+ if (xauth_filename) strcpy (xauth_filename, authfilename);
+ else {
+ fprintf(stderr,"cannot allocate memory\n");
+ return -1;
+ }
+
+ xauth_modified = False;
+
+ if (verbose) {
+ printf ("%s authority file %s\n",
+ ignore_locks ? "Ignoring locks on" : "Using", authfilename);
+ }
+ return 0;
+}
+
+static int
+write_auth_file(char *tmp_nam)
+{
+ FILE *fp = NULL;
+ int fd;
+ AuthList *list;
+
+ /*
+ * xdm and auth spec assumes auth file is 12 or fewer characters
+ */
+ strcpy (tmp_nam, xauth_filename);
+ strcat (tmp_nam, "-n"); /* for new */
+ (void) unlink (tmp_nam);
+ /* CPhipps 2000/02/12 - fix file unlink/fopen race */
+ fd = open(tmp_nam, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (fd != -1) fp = fdopen (fd, "wb");
+ if (!fp) {
+ if (fd != -1) close(fd);
+ fprintf (stderr, "%s: unable to open tmp file \"%s\"\n",
+ ProgramName, tmp_nam);
+ return -1;
+ }
+
+ /*
+ * Write MIT-MAGIC-COOKIE-1 first, because R4 Xlib knows
+ * only that and uses the first authorization it finds.
+ */
+ for (list = xauth_head; list; list = list->next) {
+ if (list->auth->name_length == 18
+ && strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) == 0) {
+ if (!XauWriteAuth(fp, list->auth)) {
+ (void) fclose(fp);
+ return -1;
+ }
+ }
+ }
+ for (list = xauth_head; list; list = list->next) {
+ if (list->auth->name_length != 18
+ || strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) != 0) {
+ if (!XauWriteAuth(fp, list->auth)) {
+ (void) fclose(fp);
+ return -1;
+ }
+ }
+ }
+
+ (void) fclose (fp);
+ return 0;
+}
+
+int
+auth_finalize(void)
+{
+ char temp_name[1024]; /* large filename size */
+
+ if (xauth_modified) {
+ if (dieing) {
+ if (verbose) {
+ /*
+ * called from a signal handler -- printf is *not* reentrant; also
+ * fileno() might not be reentrant, avoid it if possible, and use
+ * stderr instead of stdout
+ */
+#ifdef STDERR_FILENO
+ WRITES(STDERR_FILENO, "\nAborting changes to authority file ");
+ WRITES(STDERR_FILENO, xauth_filename);
+ WRITES(STDERR_FILENO, "\n");
+#else
+ WRITES(fileno(stderr), "\nAborting changes to authority file ");
+ WRITES(fileno(stderr), xauth_filename);
+ WRITES(fileno(stderr), "\n");
+#endif
+ }
+ } else if (!xauth_allowed) {
+ fprintf (stderr,
+ "%s: %s not writable, changes ignored\n",
+ ProgramName, xauth_filename);
+ } else {
+ if (verbose) {
+ printf ("%s authority file %s\n",
+ ignore_locks ? "Ignoring locks and writing" :
+ "Writing", xauth_filename);
+ }
+ temp_name[0] = '\0';
+ if (write_auth_file (temp_name) == -1) {
+ fprintf (stderr,
+ "%s: unable to write authority file %s\n",
+ ProgramName, temp_name);
+ } else {
+ (void) unlink (xauth_filename);
+#if defined(WIN32) || defined(__UNIXOS2__)|| defined(__CYGWIN__)
+ if (rename(temp_name, xauth_filename) == -1)
+#else
+ if (link (temp_name, xauth_filename) == -1)
+#endif
+ {
+ fprintf (stderr,
+ "%s: unable to link authority file %s, use %s\n",
+ ProgramName, xauth_filename, temp_name);
+ } else {
+ (void) unlink (temp_name);
+ }
+ }
+ }
+ }
+
+ if (xauth_locked) {
+ XauUnlockAuth (xauth_filename);
+ }
+ (void) umask (original_umask);
+ return 0;
+}
+
+int
+process_command(char *inputfilename, int lineno, int argc, char **argv)
+{
+ int status;
+
+ if (argc < 1 || !argv || !argv[0]) return 1;
+
+ if (dispatch_command (inputfilename, lineno, argc, argv,
+ command_table, &status))
+ return status;
+
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unknown command \"%s\"\n", argv[0]);
+ return 1;
+}
+
+
+/*
+ * utility routines
+ */
+
+static char *
+bintohex(unsigned int len, char *bindata)
+{
+ char *hexdata, *starthex;
+
+ /* two chars per byte, plus null termination */
+ starthex = hexdata = (char *)malloc(2*len + 1);
+ if (!hexdata)
+ return NULL;
+
+ for (; len > 0; len--, bindata++) {
+ register char *s = hex_table[(unsigned char)*bindata];
+ *hexdata++ = s[0];
+ *hexdata++ = s[1];
+ }
+ *hexdata = '\0';
+ return starthex;
+}
+
+static void
+fprintfhex(register FILE *fp, int len, char *cp)
+{
+ char *hex;
+
+ hex = bintohex(len, cp);
+ fprintf(fp, hex);
+ free(hex);
+}
+
+int
+dump_numeric(register FILE *fp, register Xauth *auth)
+{
+ fprintf (fp, "%04x", auth->family); /* unsigned short */
+ fprintf (fp, " %04x ", auth->address_length); /* short */
+ fprintfhex (fp, auth->address_length, auth->address);
+ fprintf (fp, " %04x ", auth->number_length); /* short */
+ fprintfhex (fp, auth->number_length, auth->number);
+ fprintf (fp, " %04x ", auth->name_length); /* short */
+ fprintfhex (fp, auth->name_length, auth->name);
+ fprintf (fp, " %04x ", auth->data_length); /* short */
+ fprintfhex (fp, auth->data_length, auth->data);
+ putc ('\n', fp);
+ return 1;
+}
+
+/* ARGSUSED */
+static int
+dump_entry(char *inputfilename, int lineno, Xauth *auth, char *data)
+{
+ struct _list_data *ld = (struct _list_data *) data;
+ FILE *fp = ld->fp;
+
+ if (ld->numeric) {
+ dump_numeric (fp, auth);
+ } else {
+ char *dpyname = NULL;
+
+ switch (auth->family) {
+ case FamilyLocal:
+ fwrite (auth->address, sizeof (char), auth->address_length, fp);
+ fprintf (fp, "/unix");
+ break;
+ case FamilyInternet:
+ case FamilyDECnet:
+ dpyname = get_hostname (auth);
+ if (dpyname) {
+ fprintf (fp, "%s", dpyname);
+ break;
+ }
+ /* else fall through to default */
+ default:
+ fprintf (fp, "#%04x#", auth->family);
+ fprintfhex (fp, auth->address_length, auth->address);
+ putc ('#', fp);
+ }
+ putc (':', fp);
+ fwrite (auth->number, sizeof (char), auth->number_length, fp);
+ putc (' ', fp);
+ putc (' ', fp);
+ fwrite (auth->name, sizeof (char), auth->name_length, fp);
+ putc (' ', fp);
+ putc (' ', fp);
+ if (!strncmp(auth->name, SECURERPC, auth->name_length) ||
+ !strncmp(auth->name, K5AUTH, auth->name_length))
+ fwrite (auth->data, sizeof (char), auth->data_length, fp);
+ else
+ fprintfhex (fp, auth->data_length, auth->data);
+ putc ('\n', fp);
+ }
+ return 0;
+}
+
+static int
+extract_entry(char *inputfilename, int lineno, Xauth *auth, char *data)
+{
+ struct _extract_data *ed = (struct _extract_data *) data;
+
+ if (!ed->fp) {
+ ed->fp = open_file (&ed->filename,
+ ed->numeric ? "w" : "wb",
+ &ed->used_stdout,
+ inputfilename, lineno, ed->cmd);
+ if (!ed->fp) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr,
+ "unable to open extraction file \"%s\"\n",
+ ed->filename);
+ return -1;
+ }
+ }
+ (*(ed->numeric ? dump_numeric : XauWriteAuth)) (ed->fp, auth);
+ ed->nwritten++;
+
+ return 0;
+}
+
+
+static int
+match_auth_dpy(register Xauth *a, register Xauth *b)
+{
+ return ((a->family == b->family &&
+ a->address_length == b->address_length &&
+ a->number_length == b->number_length &&
+ memcmp(a->address, b->address, a->address_length) == 0 &&
+ memcmp(a->number, b->number, a->number_length) == 0) ? 1 : 0);
+}
+
+/* return non-zero iff display and authorization type are the same */
+
+static int
+match_auth(register Xauth *a, register Xauth *b)
+{
+ return ((match_auth_dpy(a, b)
+ && a->name_length == b->name_length
+ && memcmp(a->name, b->name, a->name_length) == 0) ? 1 : 0);
+}
+
+
+static int
+merge_entries(AuthList **firstp, AuthList *second, int *nnewp, int *nreplp)
+{
+ AuthList *a, *b, *first, *tail;
+ int n = 0, nnew = 0, nrepl = 0;
+
+ if (!second) return 0;
+
+ if (!*firstp) { /* if nothing to merge into */
+ *firstp = second;
+ for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ;
+ *nnewp = n;
+ *nreplp = 0;
+ return n;
+ }
+
+ first = *firstp;
+ /*
+ * find end of first list and stick second list on it
+ */
+ for (tail = first; tail->next; tail = tail->next) ;
+ tail->next = second;
+
+ /*
+ * run down list freeing duplicate entries; if an entry is okay, then
+ * bump the tail up to include it, otherwise, cut the entry out of
+ * the chain.
+ */
+ for (b = second; b; ) {
+ AuthList *next = b->next; /* in case we free it */
+
+ a = first;
+ for (;;) {
+ if (match_auth (a->auth, b->auth)) { /* found a duplicate */
+ AuthList tmp; /* swap it in for old one */
+ tmp = *a;
+ *a = *b;
+ *b = tmp;
+ a->next = b->next;
+ XauDisposeAuth (b->auth);
+ free ((char *) b);
+ b = NULL;
+ tail->next = next;
+ nrepl++;
+ nnew--;
+ break;
+ }
+ if (a == tail) break; /* if have looked at left side */
+ a = a->next;
+ }
+ if (b) { /* if we didn't remove it */
+ tail = b; /* bump end of first list */
+ }
+ b = next;
+ n++;
+ nnew++;
+ }
+
+ *nnewp = nnew;
+ *nreplp = nrepl;
+ return n;
+
+}
+
+typedef int (*YesNoFunc)(char *, int, Xauth *, char *);
+
+static int
+iterdpy (char *inputfilename, int lineno, int start,
+ int argc, char *argv[],
+ YesNoFunc yfunc, YesNoFunc nfunc, char *data)
+{
+ int i;
+ int status;
+ int errors = 0;
+ Xauth proto;
+ AuthList *l, *next;
+
+ /*
+ * iterate
+ */
+ for (i = start; i < argc; i++) {
+ char *displayname = argv[i];
+ proto.address = proto.number = NULL;
+ if (!get_displayname_auth (displayname, &proto)) {
+ prefix (inputfilename, lineno);
+ baddisplayname (displayname, argv[0]);
+ errors++;
+ continue;
+ }
+ status = 0;
+ for (l = xauth_head; l; l = next) {
+ next = l->next;
+ if (match_auth_dpy (&proto, l->auth)) {
+ if (yfunc) {
+ status = (*yfunc) (inputfilename, lineno,
+ l->auth, data);
+ if (status < 0) break;
+ }
+ } else {
+ if (nfunc) {
+ status = (*nfunc) (inputfilename, lineno,
+ l->auth, data);
+ if (status < 0) break;
+ }
+ }
+ }
+ if (proto.address) free (proto.address);
+ if (proto.number) free (proto.number);
+ if (status < 0) {
+ errors -= status; /* since status is negative */
+ break;
+ }
+ }
+
+ return errors;
+}
+
+/* ARGSUSED */
+static int
+remove_entry(char *inputfilename, int lineno, Xauth *auth, char *data)
+{
+ int *nremovedp = (int *) data;
+ AuthList **listp = &xauth_head;
+ AuthList *list;
+
+ /*
+ * unlink the auth we were asked to
+ */
+ while ((list = *listp)->auth != auth)
+ listp = &list->next;
+ *listp = list->next;
+ XauDisposeAuth (list->auth); /* free the auth */
+ free (list); /* free the link */
+ xauth_modified = True;
+ (*nremovedp)++;
+ return 1;
+}
+
+/*
+ * action routines
+ */
+
+/*
+ * help
+ */
+int
+print_help(FILE *fp, char *cmd, char *prefix)
+{
+ CommandTable *ct;
+ int n = 0;
+
+ if (!prefix) prefix = "";
+
+ if (!cmd) { /* if no cmd, print all help */
+ for (ct = command_table; ct->name; ct++) {
+ fprintf (fp, "%s%s\n", prefix, ct->helptext);
+ n++;
+ }
+ } else {
+ int len = strlen (cmd);
+ for (ct = command_table; ct->name; ct++) {
+ if (strncmp (cmd, ct->name, len) == 0) {
+ fprintf (fp, "%s%s\n", prefix, ct->helptext);
+ n++;
+ }
+ }
+ }
+
+ return n;
+}
+
+static int
+do_help(char *inputfilename, int lineno, int argc, char **argv)
+{
+ char *cmd = (argc > 1 ? argv[1] : NULL);
+ int n;
+
+ n = print_help (stdout, cmd, " "); /* a nice amount */
+
+ if (n < 0 || (n == 0 && !cmd)) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "internal error with help");
+ if (cmd) {
+ fprintf (stderr, " on command \"%s\"", cmd);
+ }
+ fprintf (stderr, "\n");
+ return 1;
+ }
+
+ if (n == 0) {
+ prefix (inputfilename, lineno);
+ /* already know that cmd is set in this case */
+ fprintf (stderr, "no help for noexistent command \"%s\"\n", cmd);
+ }
+
+ return 0;
+}
+
+/*
+ * questionmark
+ */
+/* ARGSUSED */
+static int
+do_questionmark(char *inputfilename, int lineno, int argc, char **argv)
+{
+ CommandTable *ct;
+ int i;
+#define WIDEST_COLUMN 72
+ int col = WIDEST_COLUMN;
+
+ printf ("Commands:\n");
+ for (ct = command_table; ct->name; ct++) {
+ if ((col + ct->maxlen) > WIDEST_COLUMN) {
+ if (ct != command_table) {
+ putc ('\n', stdout);
+ }
+ fputs (" ", stdout);
+ col = 8; /* length of string above */
+ }
+ fputs (ct->name, stdout);
+ col += ct->maxlen;
+ for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH; i++) {
+ putc (' ', stdout);
+ col++;
+ }
+ }
+ if (col != 0) {
+ putc ('\n', stdout);
+ }
+
+ /* allow bad lines since this is help */
+ return 0;
+}
+
+/*
+ * list [displayname ...]
+ */
+static int
+do_list (char *inputfilename, int lineno, int argc, char **argv)
+{
+ struct _list_data ld;
+
+ ld.fp = stdout;
+ ld.numeric = (argv[0][0] == 'n');
+
+ if (argc == 1) {
+ register AuthList *l;
+
+ if (xauth_head) {
+ for (l = xauth_head; l; l = l->next) {
+ dump_entry (inputfilename, lineno, l->auth, (char *) &ld);
+ }
+ }
+ return 0;
+ }
+
+ return iterdpy (inputfilename, lineno, 1, argc, argv,
+ dump_entry, NULL, (char *) &ld);
+
+ return 0;
+}
+
+/*
+ * merge filename [filename ...]
+ */
+static int
+do_merge(char *inputfilename, int lineno, int argc, char **argv)
+{
+ int i;
+ int errors = 0;
+ AuthList *head, *tail, *listhead, *listtail;
+ int nentries, nnew, nrepl;
+ Bool numeric = False;
+
+ if (argc < 2) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ if (argv[0][0] == 'n') numeric = True;
+ listhead = listtail = NULL;
+
+ for (i = 1; i < argc; i++) {
+ char *filename = argv[i];
+ FILE *fp;
+ Bool used_stdin = False;
+
+ fp = open_file (&filename,
+ numeric ? "r" : "rb",
+ &used_stdin, inputfilename, lineno,
+ argv[0]);
+ if (!fp) {
+ errors++;
+ continue;
+ }
+
+ head = tail = NULL;
+ nentries = read_auth_entries (fp, numeric, &head, &tail);
+ if (nentries == 0) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to read any entries from file \"%s\"\n",
+ filename);
+ errors++;
+ } else { /* link it in */
+ add_to_list (listhead, listtail, head);
+ }
+
+ if (!used_stdin) (void) fclose (fp);
+ }
+
+ /*
+ * if we have new entries, merge them in (freeing any duplicates)
+ */
+ if (listhead) {
+ nentries = merge_entries (&xauth_head, listhead, &nnew, &nrepl);
+ if (verbose)
+ printf ("%d entries read in: %d new, %d replacement%s\n",
+ nentries, nnew, nrepl, nrepl != 1 ? "s" : "");
+ if (nentries > 0) xauth_modified = True;
+ }
+
+ return 0;
+}
+
+/*
+ * extract filename displayname [displayname ...]
+ */
+static int
+do_extract(char *inputfilename, int lineno, int argc, char **argv)
+{
+ int errors;
+ struct _extract_data ed;
+
+ if (argc < 3) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ ed.fp = NULL;
+ ed.filename = argv[1];
+ ed.numeric = (argv[0][0] == 'n');
+ ed.nwritten = 0;
+ ed.cmd = argv[0];
+
+ errors = iterdpy (inputfilename, lineno, 2, argc, argv,
+ extract_entry, NULL, (char *) &ed);
+
+ if (!ed.fp) {
+ fprintf (stderr,
+ "No matches found, authority file \"%s\" not written\n",
+ ed.filename);
+ } else {
+ if (verbose) {
+ printf ("%d entries written to \"%s\"\n",
+ ed.nwritten, ed.filename);
+ }
+ if (!ed.used_stdout) {
+ (void) fclose (ed.fp);
+ }
+ }
+
+ return errors;
+}
+
+
+/*
+ * add displayname protocolname hexkey
+ */
+static int
+do_add(char *inputfilename, int lineno, int argc, char **argv)
+{
+ int n, nnew, nrepl;
+ int len;
+ char *dpyname;
+ char *protoname;
+ char *hexkey;
+ char *key;
+ Xauth *auth;
+ AuthList *list;
+
+ if (argc != 4 || !argv[1] || !argv[2] || !argv[3]) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ dpyname = argv[1];
+ protoname = argv[2];
+ hexkey = argv[3];
+
+ len = strlen(hexkey);
+ if (hexkey[0] == '"' && hexkey[len-1] == '"') {
+ key = malloc(len-1);
+ strncpy(key, hexkey+1, len-2);
+ len -= 2;
+ } else if (!strcmp(protoname, SECURERPC) ||
+ !strcmp(protoname, K5AUTH)) {
+ key = malloc(len+1);
+ strcpy(key, hexkey);
+ } else {
+ len = cvthexkey (hexkey, &key);
+ if (len < 0) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr,
+ "key contains odd number of or non-hex characters\n");
+ return 1;
+ }
+ }
+
+ auth = (Xauth *) malloc (sizeof (Xauth));
+ if (!auth) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to allocate %ld bytes for Xauth structure\n",
+ (unsigned long)sizeof (Xauth));
+ free (key);
+ return 1;
+ }
+
+ if (!get_displayname_auth (dpyname, auth)) {
+ prefix (inputfilename, lineno);
+ baddisplayname (dpyname, argv[0]);
+ free (auth);
+ free (key);
+ return 1;
+ }
+
+ /*
+ * allow an abbreviation for common protocol names
+ */
+ if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV) == 0) {
+ protoname = DEFAULT_PROTOCOL;
+ }
+
+ auth->name_length = strlen (protoname);
+ auth->name = copystring (protoname, auth->name_length);
+ if (!auth->name) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to allocate %d character protocol name\n",
+ auth->name_length);
+ free (auth);
+ free (key);
+ return 1;
+ }
+ auth->data_length = len;
+ auth->data = key;
+
+ list = (AuthList *) malloc (sizeof (AuthList));
+ if (!list) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to allocate %ld bytes for auth list\n",
+ (unsigned long)sizeof (AuthList));
+ free (auth);
+ free (key);
+ free (auth->name);
+ return 1;
+ }
+
+ list->next = NULL;
+ list->auth = auth;
+
+ /*
+ * merge it in; note that merge will deal with allocation
+ */
+ n = merge_entries (&xauth_head, list, &nnew, &nrepl);
+ if (n <= 0) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to merge in added record\n");
+ return 1;
+ }
+
+ xauth_modified = True;
+ return 0;
+}
+
+/*
+ * remove displayname
+ */
+static int
+do_remove(char *inputfilename, int lineno, int argc, char **argv)
+{
+ int nremoved = 0;
+ int errors;
+
+ if (argc < 2) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ errors = iterdpy (inputfilename, lineno, 1, argc, argv,
+ remove_entry, NULL, (char *) &nremoved);
+ if (verbose) printf ("%d entries removed\n", nremoved);
+ return errors;
+}
+
+/*
+ * info
+ */
+static int
+do_info(char *inputfilename, int lineno, int argc, char **argv)
+{
+ int n;
+ AuthList *l;
+
+ if (argc != 1) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ for (l = xauth_head, n = 0; l; l = l->next, n++) ;
+
+ printf ("Authority file: %s\n",
+ xauth_filename ? xauth_filename : "(none)");
+ printf ("File new: %s\n", xauth_existed ? No : Yes);
+ printf ("File locked: %s\n", xauth_locked ? No : Yes);
+ printf ("Number of entries: %d\n", n);
+ printf ("Changes honored: %s\n", xauth_allowed ? Yes : No);
+ printf ("Changes made: %s\n", xauth_modified ? Yes : No);
+ printf ("Current input: %s:%d\n", inputfilename, lineno);
+ return 0;
+}
+
+
+/*
+ * exit
+ */
+static Bool alldone = False;
+
+/* ARGSUSED */
+static int
+do_exit(char *inputfilename, int lineno, int argc, char **argv)
+{
+ /* allow bogus stuff */
+ alldone = True;
+ return 0;
+}
+
+/*
+ * quit
+ */
+/* ARGSUSED */
+static int
+do_quit(char *inputfilename, int lineno, int argc, char **argv)
+{
+ /* allow bogus stuff */
+ die (0);
+ /* NOTREACHED */
+ return -1; /* for picky compilers */
+}
+
+
+/*
+ * source filename
+ */
+static int
+do_source(char *inputfilename, int lineno, int argc, char **argv)
+{
+ char *script;
+ char buf[BUFSIZ];
+ FILE *fp;
+ Bool used_stdin = False;
+ int len;
+ int errors = 0, status;
+ int sublineno = 0;
+ char **subargv;
+ int subargc;
+ Bool prompt = False; /* only true if reading from tty */
+
+ if (argc != 2 || !argv[1]) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ script = argv[1];
+
+ fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]);
+ if (!fp) {
+ return 1;
+ }
+
+ if (verbose && used_stdin && isatty (fileno (fp))) prompt = True;
+
+ while (!alldone) {
+ buf[0] = '\0';
+ if (prompt) {
+ printf ("xauth> ");
+ fflush (stdout);
+ }
+ if (fgets (buf, sizeof buf, fp) == NULL) break;
+ sublineno++;
+ len = strlen (buf);
+ if (len == 0 || buf[0] == '#') continue;
+ if (buf[len-1] != '\n') {
+ prefix (script, sublineno);
+ fprintf (stderr, "line too long\n");
+ errors++;
+ break;
+ }
+ buf[--len] = '\0'; /* remove new line */
+ subargv = split_into_words (buf, &subargc);
+ if (subargv) {
+ status = process_command (script, sublineno, subargc, subargv);
+ free ((char *) subargv);
+ errors += status;
+ } else {
+ prefix (script, sublineno);
+ fprintf (stderr, "unable to break line into words\n");
+ errors++;
+ }
+ }
+
+ if (!used_stdin) {
+ (void) fclose (fp);
+ }
+ return errors;
+}
+
+/*static int
+static int x_protocol_error;
+catch_x_protocol_error(Display *dpy, XErrorEvent *errevent)
+{
+ char buf[80];
+ XGetErrorText(dpy, errevent->error_code, buf, sizeof (buf));
+ fprintf(stderr, "%s\n", buf);
+ x_protocol_error = errevent->error_code;
+ return 1;
+}
+*/
+/*
+ * generate
+ */
+/*static int
+do_generate(char *inputfilename, int lineno, int argc, char **argv)
+{
+ char *displayname;
+ int major_version, minor_version;
+ XSecurityAuthorization id_return;
+ Xauth *auth_in, *auth_return;
+ XSecurityAuthorizationAttributes attributes;
+ unsigned long attrmask = 0;
+ Display *dpy;
+ int status;
+ char *args[4];
+ char *protoname = ".";
+ int i;
+ int authdatalen = 0;
+ char *hexdata;
+ char *authdata = NULL;
+
+ if (argc < 2 || !argv[1]) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[0]);
+ return 1;
+ }
+
+ displayname = argv[1];
+
+ if (argc > 2) {
+ protoname = argv[2];
+ }
+
+ for (i = 3; i < argc; i++) {
+ if (0 == strcmp(argv[i], "timeout")) {
+ if (++i == argc) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[i-1]);
+ return 1;
+ }
+ attributes.timeout = atoi(argv[i]);
+ attrmask |= XSecurityTimeout;
+
+ } else if (0 == strcmp(argv[i], "trusted")) {
+ attributes.trust_level = XSecurityClientTrusted;
+ attrmask |= XSecurityTrustLevel;
+
+ } else if (0 == strcmp(argv[i], "untrusted")) {
+ attributes.trust_level = XSecurityClientUntrusted;
+ attrmask |= XSecurityTrustLevel;
+
+ } else if (0 == strcmp(argv[i], "group")) {
+ if (++i == argc) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[i-1]);
+ return 1;
+ }
+ attributes.group = atoi(argv[i]);
+ attrmask |= XSecurityGroup;
+
+ } else if (0 == strcmp(argv[i], "data")) {
+ if (++i == argc) {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[i-1]);
+ return 1;
+ }
+ hexdata = argv[i];
+ authdatalen = strlen(hexdata);
+ if (hexdata[0] == '"' && hexdata[authdatalen-1] == '"') {
+ authdata = malloc(authdatalen-1);
+ strncpy(authdata, hexdata+1, authdatalen-2);
+ authdatalen -= 2;
+ } else {
+ authdatalen = cvthexkey (hexdata, &authdata);
+ if (authdatalen < 0) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr,
+ "data contains odd number of or non-hex characters\n");
+ return 1;
+ }
+ }
+ } else {
+ prefix (inputfilename, lineno);
+ badcommandline (argv[i]);
+ return 1;
+ }
+ }
+
+ // generate authorization using the Security extension /
+
+ dpy = XOpenDisplay (displayname);
+ if (!dpy) {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "unable to open display \"%s\".\n", displayname);
+ return 1;
+ }
+
+ status = XSecurityQueryExtension(dpy, &major_version, &minor_version);
+ if (!status)
+ {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "couldn't query Security extension on display \"%s\"\n",
+ displayname);
+ return 1;
+ }
+
+ // fill in input Xauth struct /
+
+ auth_in = XSecurityAllocXauth();
+ if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV) == 0) {
+ auth_in->name = DEFAULT_PROTOCOL;
+ }
+ else
+ auth_in->name = protoname;
+ auth_in->name_length = strlen(auth_in->name);
+ auth_in->data = authdata;
+ auth_in->data_length = authdatalen;
+
+ x_protocol_error = 0;
+ XSetErrorHandler(catch_x_protocol_error);
+ auth_return = XSecurityGenerateAuthorization(dpy, auth_in, attrmask,
+ &attributes, &id_return);
+ XSync(dpy, False);
+
+ if (!auth_return || x_protocol_error)
+ {
+ prefix (inputfilename, lineno);
+ fprintf (stderr, "couldn't generate authorization\n");
+ return 1;
+ }
+
+ if (verbose)
+ printf("authorization id is %ld\n", id_return);
+
+ // create a fake input line to give to do_add /
+
+ args[0] = "add";
+ args[1] = displayname;
+ args[2] = auth_in->name;
+ args[3] = bintohex(auth_return->data_length, auth_return->data);
+
+ status = do_add(inputfilename, lineno, 4, args);
+
+ if (authdata) free(authdata);
+ XSecurityFreeXauth(auth_in);
+ XSecurityFreeXauth(auth_return);
+ free(args[3]); // hex data /
+ XCloseDisplay(dpy);
+ return status;
+}
+*/
diff --git a/nx-X11/programs/nxauth/xauth.c b/nx-X11/programs/nxauth/xauth.c
new file mode 100644
index 000000000..5a37c34c8
--- /dev/null
+++ b/nx-X11/programs/nxauth/xauth.c
@@ -0,0 +1,184 @@
+/*
+ * $Xorg: xauth.c,v 1.4 2001/02/09 02:05:38 xorgcvs Exp $
+ *
+ * xauth - manipulate authorization file
+ *
+ *
+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.
+ * *
+ * Author: Jim Fulton, MIT X Consortium
+ */
+/* $XFree86: xc/programs/xauth/xauth.c,v 1.5 2001/12/14 20:01:15 dawes Exp $ */
+
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAUTH, 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 Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include "xauth.h"
+
+
+/*
+ * global data
+ */
+char *ProgramName; /* argv[0], set at top of main() */
+int verbose = -1; /* print certain messages */
+Bool ignore_locks = True; /* for error recovery */
+Bool break_locks = False; /* for error recovery */
+
+/*
+ * local data
+ */
+
+static char *authfilename = NULL; /* filename of cookie file */
+static char *defcmds[] = { "source", "-", NULL }; /* default command */
+static int ndefcmds = 2;
+static char *defsource = "(stdin)";
+
+/*
+ * utility routines
+ */
+static void
+usage(void)
+{
+ static char *prefixmsg[] = {
+"",
+"where options include:",
+" -f authfilename name of authority file to use",
+" -v turn on extra messages",
+" -q turn off extra messages",
+" -i ignore locks on authority file",
+" -b break locks on authority file",
+"",
+"and commands have the following syntax:",
+"",
+NULL };
+ static char *suffixmsg[] = {
+"A dash may be used with the \"merge\" and \"source\" to read from the",
+"standard input. Commands beginning with \"n\" use numeric format.",
+"",
+NULL };
+ char **msg;
+
+ fprintf (stderr, "usage: %s [-options ...] [command arg ...]\n",
+ ProgramName);
+ for (msg = prefixmsg; *msg; msg++) {
+ fprintf (stderr, "%s\n", *msg);
+ }
+ print_help (stderr, NULL, " "); /* match prefix indentation */
+ fprintf (stderr, "\n");
+ for (msg = suffixmsg; *msg; msg++) {
+ fprintf (stderr, "%s\n", *msg);
+ }
+ exit (1);
+}
+
+
+/*
+ * The main routine - parses command line and calls action procedures
+ */
+int
+main(int argc, char *argv[])
+{
+ int i;
+ char *sourcename = defsource;
+ char **arglist = defcmds;
+ int nargs = ndefcmds;
+ int status;
+
+ ProgramName = argv[0];
+
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+
+ if (arg[0] == '-') {
+ char *flag;
+
+ for (flag = (arg + 1); *flag; flag++) {
+ switch (*flag) {
+ case 'f': /* -f authfilename */
+ if (++i >= argc) usage ();
+ authfilename = argv[i];
+ continue;
+ case 'v': /* -v */
+ verbose = 1;
+ continue;
+ case 'q': /* -q */
+ verbose = 0;
+ continue;
+ case 'b': /* -b */
+ break_locks = True;
+ continue;
+ case 'i': /* -i */
+ ignore_locks = True;
+ continue;
+ default:
+ usage ();
+ }
+ }
+ } else {
+ sourcename = "(argv)";
+ nargs = argc - i;
+ arglist = argv + i;
+ if (verbose == -1) verbose = 0;
+ break;
+ }
+ }
+
+ if (verbose == -1) { /* set default, don't junk stdout */
+ verbose = (isatty(fileno(stdout)) != 0);
+ }
+
+ if (!authfilename) {
+ authfilename = XauFileName (); /* static name, do not free */
+ if (!authfilename) {
+ fprintf (stderr,
+ "%s: unable to generate an authority file name\n",
+ ProgramName);
+ exit (1);
+ }
+ }
+ if (auth_initialize (authfilename) != 0) {
+ /* error message printed in auth_initialize */
+ exit (1);
+ }
+
+ status = process_command (sourcename, 1, nargs, arglist);
+
+ (void) auth_finalize ();
+ exit ((status != 0) ? 1 : 0);
+}
+
+
diff --git a/nx-X11/programs/nxauth/xauth.h b/nx-X11/programs/nxauth/xauth.h
new file mode 100644
index 000000000..33a6c4e3b
--- /dev/null
+++ b/nx-X11/programs/nxauth/xauth.h
@@ -0,0 +1,58 @@
+/*
+ * $Xorg: xauth.h,v 1.4 2001/02/09 02:05:38 xorgcvs 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.
+ * *
+ * Author: Jim Fulton, MIT X Consortium
+ */
+/* $XFree86: xc/programs/xauth/xauth.h,v 1.6 2001/12/14 20:01:15 dawes Exp $ */
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <X11/Xauth.h>
+#include <X11/Xfuncs.h>
+
+#ifndef True
+typedef int Bool;
+#define False 0
+#define True 1
+#endif
+
+extern char *ProgramName;
+
+#include <stdlib.h>
+
+extern char *get_hostname ( Xauth *auth );
+extern char *get_address_info ( int family, char *fulldpyname, int prefix, char *host, int *lenp );
+extern char *copystring ( char *src, int len );
+extern char *get_local_hostname ( char *buf, int maxlen );
+extern Bool parse_displayname ( char *displayname, int *familyp, char **hostp, int *dpynump, int *scrnump, char **restp );
+extern int auth_initialize ( char *authfilename );
+extern int auth_finalize ( void );
+extern int process_command ( char *inputfilename, int lineno, int argc, char **argv );
+extern int dump_numeric ( FILE *fp, Xauth *auth );
+extern int print_help ( FILE *fp, char *cmd, char *prefix );
+extern int verbose;
+extern Bool ignore_locks;
+extern Bool break_locks;